@doenet/doenetml 0.6.0-alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +3 -0
- package/LICENSE +661 -0
- package/README.md +146 -0
- package/cypress/e2e/ActivityViewer/activityVariants.cy.js +1770 -0
- package/cypress/e2e/ActivityViewer/compiledActivity.cy.js +83 -0
- package/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +697 -0
- package/cypress/e2e/answerValidation/errorinnumbers.cy.js +2125 -0
- package/cypress/e2e/answerValidation/factoring.cy.js +1945 -0
- package/cypress/e2e/answerValidation/factoringOldAlgorithm.cy.js +892 -0
- package/cypress/e2e/answerValidation/functionanswers.cy.js +314 -0
- package/cypress/e2e/answerValidation/matchingpatterns.cy.js +287 -0
- package/cypress/e2e/answerValidation/matchpartial.cy.js +6711 -0
- package/cypress/e2e/answerValidation/pointlocation.cy.js +3989 -0
- package/cypress/e2e/answerValidation/symbolicequality.cy.js +1893 -0
- package/cypress/e2e/answerValidation/videoProgress.cy.js +210 -0
- package/cypress/e2e/assignNames/basiccopy.cy.js +2376 -0
- package/cypress/e2e/assignNames/collections.cy.js +9247 -0
- package/cypress/e2e/assignNames/selects.cy.js +105 -0
- package/cypress/e2e/assignNames/sequences.cy.js +1964 -0
- package/cypress/e2e/baseComponent/basecomponentproperties.cy.js +999 -0
- package/cypress/e2e/baseComponent/doenetMLtext.cy.js +427 -0
- package/cypress/e2e/chemistry/atom.cy.js +201 -0
- package/cypress/e2e/chemistry/ion.cy.js +608 -0
- package/cypress/e2e/chemistry/ioniccompound.cy.js +133 -0
- package/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +2653 -0
- package/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +311 -0
- package/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +279 -0
- package/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +283 -0
- package/cypress/e2e/dynamicalsystem/odesystem.cy.js +1834 -0
- package/cypress/e2e/equality/mathexpressions.cy.js +948 -0
- package/cypress/e2e/graphing/graphreferences.cy.js +978 -0
- package/cypress/e2e/graphing/graphreferences2.cy.js +615 -0
- package/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js +401 -0
- package/cypress/e2e/tagSpecific/angle.cy.js +3898 -0
- package/cypress/e2e/tagSpecific/animatefromsequence.cy.js +2306 -0
- package/cypress/e2e/tagSpecific/answer.cy.js +31647 -0
- package/cypress/e2e/tagSpecific/bestfitline.cy.js +612 -0
- package/cypress/e2e/tagSpecific/blockquote.cy.js +30 -0
- package/cypress/e2e/tagSpecific/boolean.cy.js +742 -0
- package/cypress/e2e/tagSpecific/booleaninput.cy.js +1283 -0
- package/cypress/e2e/tagSpecific/booleanlist.cy.js +588 -0
- package/cypress/e2e/tagSpecific/booleanoperators.cy.js +596 -0
- package/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +498 -0
- package/cypress/e2e/tagSpecific/callaction.cy.js +2835 -0
- package/cypress/e2e/tagSpecific/choiceinput.cy.js +3205 -0
- package/cypress/e2e/tagSpecific/circle.cy.js +22036 -0
- package/cypress/e2e/tagSpecific/codeeditor.cy.js +1995 -0
- package/cypress/e2e/tagSpecific/collect.cy.js +5035 -0
- package/cypress/e2e/tagSpecific/componentsize.cy.js +502 -0
- package/cypress/e2e/tagSpecific/conditionalcontent.cy.js +3495 -0
- package/cypress/e2e/tagSpecific/contentBrowser.cy.js +335 -0
- package/cypress/e2e/tagSpecific/contentpicker.cy.js +261 -0
- package/cypress/e2e/tagSpecific/copy.cy.js +12627 -0
- package/cypress/e2e/tagSpecific/copy2.cy.js +5698 -0
- package/cypress/e2e/tagSpecific/curve.bezier.cy.js +12440 -0
- package/cypress/e2e/tagSpecific/curve.cy.js +1716 -0
- package/cypress/e2e/tagSpecific/curve.function.cy.js +1471 -0
- package/cypress/e2e/tagSpecific/curve.parametrized.cy.js +920 -0
- package/cypress/e2e/tagSpecific/document.cy.js +234 -0
- package/cypress/e2e/tagSpecific/endpoint.cy.js +197 -0
- package/cypress/e2e/tagSpecific/evaluate.cy.js +8895 -0
- package/cypress/e2e/tagSpecific/extract.cy.js +2282 -0
- package/cypress/e2e/tagSpecific/feedback.cy.js +2941 -0
- package/cypress/e2e/tagSpecific/function.cy.js +9450 -0
- package/cypress/e2e/tagSpecific/functioniterates.cy.js +1178 -0
- package/cypress/e2e/tagSpecific/functionoperators.cy.js +4047 -0
- package/cypress/e2e/tagSpecific/graph.cy.js +2491 -0
- package/cypress/e2e/tagSpecific/group.cy.js +683 -0
- package/cypress/e2e/tagSpecific/hint.cy.js +204 -0
- package/cypress/e2e/tagSpecific/image.cy.js +770 -0
- package/cypress/e2e/tagSpecific/integer.cy.js +206 -0
- package/cypress/e2e/tagSpecific/label.cy.js +800 -0
- package/cypress/e2e/tagSpecific/legend.cy.js +1001 -0
- package/cypress/e2e/tagSpecific/line.cy.js +12167 -0
- package/cypress/e2e/tagSpecific/linesegment.cy.js +4749 -0
- package/cypress/e2e/tagSpecific/lorem.cy.js +289 -0
- package/cypress/e2e/tagSpecific/map.cy.js +4476 -0
- package/cypress/e2e/tagSpecific/matchespattern.cy.js +693 -0
- package/cypress/e2e/tagSpecific/math.cy.js +10990 -0
- package/cypress/e2e/tagSpecific/mathdisplay.cy.js +2689 -0
- package/cypress/e2e/tagSpecific/mathinput.cy.js +15628 -0
- package/cypress/e2e/tagSpecific/mathinputgraph.cy.js +566 -0
- package/cypress/e2e/tagSpecific/mathlist.cy.js +4073 -0
- package/cypress/e2e/tagSpecific/mathoperators.cy.js +13851 -0
- package/cypress/e2e/tagSpecific/matrix.cy.js +8825 -0
- package/cypress/e2e/tagSpecific/matrixinput.cy.js +16277 -0
- package/cypress/e2e/tagSpecific/module.cy.js +1771 -0
- package/cypress/e2e/tagSpecific/number.cy.js +2221 -0
- package/cypress/e2e/tagSpecific/numberlist.cy.js +1285 -0
- package/cypress/e2e/tagSpecific/p.cy.js +72 -0
- package/cypress/e2e/tagSpecific/paginator.cy.js +2983 -0
- package/cypress/e2e/tagSpecific/parabola.cy.js +14331 -0
- package/cypress/e2e/tagSpecific/paragraphmarkup.cy.js +104 -0
- package/cypress/e2e/tagSpecific/periodicset.cy.js +1439 -0
- package/cypress/e2e/tagSpecific/piecewisefunction.cy.js +1055 -0
- package/cypress/e2e/tagSpecific/pluralize.cy.js +274 -0
- package/cypress/e2e/tagSpecific/point.cy.js +8895 -0
- package/cypress/e2e/tagSpecific/point2.cy.js +10259 -0
- package/cypress/e2e/tagSpecific/polygon.cy.js +5039 -0
- package/cypress/e2e/tagSpecific/polyline.cy.js +4704 -0
- package/cypress/e2e/tagSpecific/problem.cy.js +2768 -0
- package/cypress/e2e/tagSpecific/ray.cy.js +10770 -0
- package/cypress/e2e/tagSpecific/rectangle.cy.js +2143 -0
- package/cypress/e2e/tagSpecific/ref.cy.js +420 -0
- package/cypress/e2e/tagSpecific/regularPolygon.cy.js +1006 -0
- package/cypress/e2e/tagSpecific/regularPolygon2.cy.js +100 -0
- package/cypress/e2e/tagSpecific/regularPolygon3.cy.js +777 -0
- package/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +3619 -0
- package/cypress/e2e/tagSpecific/sectioning.cy.js +3530 -0
- package/cypress/e2e/tagSpecific/select.cy.js +5376 -0
- package/cypress/e2e/tagSpecific/selectfromsequence.cy.js +3846 -0
- package/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +2914 -0
- package/cypress/e2e/tagSpecific/sequence.cy.js +2093 -0
- package/cypress/e2e/tagSpecific/shuffle.cy.js +490 -0
- package/cypress/e2e/tagSpecific/sidebyside.cy.js +8057 -0
- package/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +72 -0
- package/cypress/e2e/tagSpecific/slider.cy.js +914 -0
- package/cypress/e2e/tagSpecific/solution.cy.js +109 -0
- package/cypress/e2e/tagSpecific/solveequations.cy.js +1026 -0
- package/cypress/e2e/tagSpecific/sort.cy.js +1685 -0
- package/cypress/e2e/tagSpecific/spreadsheet.cy.js +5971 -0
- package/cypress/e2e/tagSpecific/subsetofreals.cy.js +2725 -0
- package/cypress/e2e/tagSpecific/substitute.cy.js +2646 -0
- package/cypress/e2e/tagSpecific/tabular.cy.js +36 -0
- package/cypress/e2e/tagSpecific/text.cy.js +975 -0
- package/cypress/e2e/tagSpecific/textinput.cy.js +2177 -0
- package/cypress/e2e/tagSpecific/textlist.cy.js +369 -0
- package/cypress/e2e/tagSpecific/triangle.cy.js +1936 -0
- package/cypress/e2e/tagSpecific/triggerset.cy.js +2023 -0
- package/cypress/e2e/tagSpecific/updatevalue.cy.js +3288 -0
- package/cypress/e2e/tagSpecific/vector.cy.js +20183 -0
- package/cypress/e2e/tagSpecific/video.cy.js +612 -0
- package/cypress/e2e/tagSpecific/when.cy.js +202 -0
- package/cypress/e2e/variants/specifysinglevariant.cy.js +6726 -0
- package/cypress/e2e/variants/uniquevariants.cy.js +4846 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/support/commands.js +32 -0
- package/cypress/support/e2e.js +31 -0
- package/cypress.config.js +18 -0
- package/docs/codeSnippet.jsx +11 -0
- package/docs/index.html +133 -0
- package/docs/index.jsx +138 -0
- package/docs/prism.css +3 -0
- package/index.html +14 -0
- package/index.js +21 -0
- package/media/answer_example.png +0 -0
- package/media/graph_example.png +0 -0
- package/media/graph_markup_example.png +0 -0
- package/package.json +83 -0
- package/public/favicon.ico +0 -0
- package/public/fonts/files/open-sans-v18-latin-700.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-light.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-regular.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
- package/src/Core/ComponentTypes.js +426 -0
- package/src/Core/Core.js +11852 -0
- package/src/Core/CoreWorker.js +127 -0
- package/src/Core/Dependencies.js +8226 -0
- package/src/Core/Numerics.js +473 -0
- package/src/Core/ParameterStack.js +36 -0
- package/src/Core/ReadOnlyProxyHandler.js +41 -0
- package/src/Core/StateProxyHandler.js +88 -0
- package/src/Core/components/Aliases.js +67 -0
- package/src/Core/components/Angle.js +758 -0
- package/src/Core/components/AnimateFromSequence.js +922 -0
- package/src/Core/components/Answer.js +2087 -0
- package/src/Core/components/AsList.js +83 -0
- package/src/Core/components/AttractTo.js +245 -0
- package/src/Core/components/AttractToAngles.js +262 -0
- package/src/Core/components/AttractToConstraint.js +104 -0
- package/src/Core/components/AttractToGrid.js +315 -0
- package/src/Core/components/Award.js +906 -0
- package/src/Core/components/BestFitLine.js +318 -0
- package/src/Core/components/BezierControls.js +719 -0
- package/src/Core/components/BlockQuote.js +35 -0
- package/src/Core/components/Boolean.js +500 -0
- package/src/Core/components/BooleanInput.js +330 -0
- package/src/Core/components/BooleanList.js +396 -0
- package/src/Core/components/BooleanOperators.js +35 -0
- package/src/Core/components/BooleanOperatorsOfMath.js +148 -0
- package/src/Core/components/CallAction.js +261 -0
- package/src/Core/components/Caption.js +73 -0
- package/src/Core/components/Case.js +56 -0
- package/src/Core/components/Cell.js +439 -0
- package/src/Core/components/CellBlock.js +64 -0
- package/src/Core/components/Chart.js +795 -0
- package/src/Core/components/Choice.js +266 -0
- package/src/Core/components/ChoiceInput.js +1407 -0
- package/src/Core/components/Circle.js +2884 -0
- package/src/Core/components/CodeEditor.js +647 -0
- package/src/Core/components/CodeViewer.js +294 -0
- package/src/Core/components/CollaborateGroupSetup.js +46 -0
- package/src/Core/components/CollaborateGroups.js +119 -0
- package/src/Core/components/Collect.js +850 -0
- package/src/Core/components/Column.js +608 -0
- package/src/Core/components/ConditionalContent.js +468 -0
- package/src/Core/components/ConsiderAsResponses.js +49 -0
- package/src/Core/components/ConstrainTo.js +161 -0
- package/src/Core/components/ConstrainToAngles.js +244 -0
- package/src/Core/components/ConstrainToGraph.js +142 -0
- package/src/Core/components/ConstrainToGrid.js +175 -0
- package/src/Core/components/ConstraintUnion.js +119 -0
- package/src/Core/components/Constraints.js +497 -0
- package/src/Core/components/ContentBrowser.js +441 -0
- package/src/Core/components/ContentPicker.js +263 -0
- package/src/Core/components/ControlVectors.js +25 -0
- package/src/Core/components/Coords.js +63 -0
- package/src/Core/components/Copy.js +3412 -0
- package/src/Core/components/Curve.js +4130 -0
- package/src/Core/components/CustomAttribute.js +175 -0
- package/src/Core/components/DataFrame.js +357 -0
- package/src/Core/components/DiscreteSimulationResultList.js +342 -0
- package/src/Core/components/DiscreteSimulationResultPolyline.js +581 -0
- package/src/Core/components/Divisions.js +55 -0
- package/src/Core/components/Document.js +888 -0
- package/src/Core/components/Embed.js +65 -0
- package/src/Core/components/Endpoint.js +62 -0
- package/src/Core/components/Evaluate.js +321 -0
- package/src/Core/components/Extract.js +656 -0
- package/src/Core/components/Extrema.js +556 -0
- package/src/Core/components/Feedback.js +200 -0
- package/src/Core/components/FeedbackDefinitions.js +97 -0
- package/src/Core/components/Figure.js +148 -0
- package/src/Core/components/Footnote.js +73 -0
- package/src/Core/components/Function.js +5344 -0
- package/src/Core/components/FunctionIterates.js +306 -0
- package/src/Core/components/FunctionOperators.js +702 -0
- package/src/Core/components/Graph.js +1679 -0
- package/src/Core/components/Group.js +7 -0
- package/src/Core/components/HasSameFactoring.js +407 -0
- package/src/Core/components/Hint.js +241 -0
- package/src/Core/components/Image.js +524 -0
- package/src/Core/components/Indexing.js +79 -0
- package/src/Core/components/IntComma.js +64 -0
- package/src/Core/components/Integer.js +81 -0
- package/src/Core/components/Intersection.js +328 -0
- package/src/Core/components/Interval.js +29 -0
- package/src/Core/components/Label.js +492 -0
- package/src/Core/components/Latex.js +104 -0
- package/src/Core/components/Legend.js +329 -0
- package/src/Core/components/Line.js +2040 -0
- package/src/Core/components/LineSegment.js +882 -0
- package/src/Core/components/Lists.js +180 -0
- package/src/Core/components/Lorem.js +249 -0
- package/src/Core/components/MMeMen.js +377 -0
- package/src/Core/components/Map.js +873 -0
- package/src/Core/components/Markers.js +101 -0
- package/src/Core/components/MatchesPattern.js +339 -0
- package/src/Core/components/Math.js +2552 -0
- package/src/Core/components/MathInput.js +948 -0
- package/src/Core/components/MathList.js +828 -0
- package/src/Core/components/MathOperators.js +1286 -0
- package/src/Core/components/Matrix.js +497 -0
- package/src/Core/components/MatrixInput.js +3157 -0
- package/src/Core/components/MdMdnMrow.js +394 -0
- package/src/Core/components/Module.js +16 -0
- package/src/Core/components/Number.js +1031 -0
- package/src/Core/components/NumberList.js +550 -0
- package/src/Core/components/Option.js +24 -0
- package/src/Core/components/P.js +71 -0
- package/src/Core/components/Paginator.js +338 -0
- package/src/Core/components/Panel.js +126 -0
- package/src/Core/components/Parabola.js +1561 -0
- package/src/Core/components/ParagraphMarkup.js +59 -0
- package/src/Core/components/Pegboard.js +43 -0
- package/src/Core/components/PeriodicSet.js +291 -0
- package/src/Core/components/PiecewiseFunction.js +832 -0
- package/src/Core/components/Pluralize.js +198 -0
- package/src/Core/components/Point.js +1295 -0
- package/src/Core/components/Polygon.js +408 -0
- package/src/Core/components/Polyline.js +841 -0
- package/src/Core/components/RandomizedTextList.js +225 -0
- package/src/Core/components/Ray.js +1737 -0
- package/src/Core/components/Rectangle.js +1535 -0
- package/src/Core/components/Ref.js +350 -0
- package/src/Core/components/RegionBetweenCurveXAxis.js +124 -0
- package/src/Core/components/RegionHalfPlane.js +107 -0
- package/src/Core/components/RegularPolygon.js +2118 -0
- package/src/Core/components/RenderDoenetML.js +181 -0
- package/src/Core/components/Row.js +780 -0
- package/src/Core/components/SampleRandomNumbers.js +653 -0
- package/src/Core/components/Sectioning.js +303 -0
- package/src/Core/components/Select.js +947 -0
- package/src/Core/components/SelectFromSequence.js +1242 -0
- package/src/Core/components/SelectRandomNumbers.js +225 -0
- package/src/Core/components/Sequence.js +444 -0
- package/src/Core/components/Setup.js +53 -0
- package/src/Core/components/Shuffle.js +470 -0
- package/src/Core/components/SideBySide.js +2130 -0
- package/src/Core/components/SingleCharacterComponents.js +41 -0
- package/src/Core/components/Slider.js +819 -0
- package/src/Core/components/SolutionContainer.js +67 -0
- package/src/Core/components/Solutions.js +334 -0
- package/src/Core/components/SolveEquations.js +568 -0
- package/src/Core/components/Sort.js +398 -0
- package/src/Core/components/Sources.js +108 -0
- package/src/Core/components/Split.js +205 -0
- package/src/Core/components/Spreadsheet.js +1507 -0
- package/src/Core/components/StyleDefinitions.js +111 -0
- package/src/Core/components/SubsetOfReals.js +348 -0
- package/src/Core/components/SubsetOfRealsInput.js +1474 -0
- package/src/Core/components/Substitute.js +496 -0
- package/src/Core/components/SummaryStatistics.js +652 -0
- package/src/Core/components/Table.js +145 -0
- package/src/Core/components/Tabular.js +384 -0
- package/src/Core/components/Template.js +360 -0
- package/src/Core/components/Text.js +341 -0
- package/src/Core/components/TextInput.js +566 -0
- package/src/Core/components/TextList.js +442 -0
- package/src/Core/components/TextListFromString.js +137 -0
- package/src/Core/components/TextOperatorsOfMath.js +21 -0
- package/src/Core/components/Triangle.js +280 -0
- package/src/Core/components/TriggerSet.js +189 -0
- package/src/Core/components/TupleList.js +43 -0
- package/src/Core/components/UpdateValue.js +435 -0
- package/src/Core/components/VariantControl.js +36 -0
- package/src/Core/components/Vector.js +2478 -0
- package/src/Core/components/Verbatim.js +125 -0
- package/src/Core/components/Video.js +673 -0
- package/src/Core/components/When.js +198 -0
- package/src/Core/components/abstract/AngleListComponent.js +140 -0
- package/src/Core/components/abstract/BaseComponent.js +1496 -0
- package/src/Core/components/abstract/BlockComponent.js +5 -0
- package/src/Core/components/abstract/BooleanBaseOperator.js +88 -0
- package/src/Core/components/abstract/BooleanBaseOperatorOfMath.js +100 -0
- package/src/Core/components/abstract/BooleanBaseOperatorOneInput.js +44 -0
- package/src/Core/components/abstract/ComponentSize.js +789 -0
- package/src/Core/components/abstract/ComponentWithSelectableType.js +537 -0
- package/src/Core/components/abstract/CompositeComponent.js +142 -0
- package/src/Core/components/abstract/ConstraintComponent.js +19 -0
- package/src/Core/components/abstract/FunctionBaseOperator.js +680 -0
- package/src/Core/components/abstract/GraphicalComponent.js +56 -0
- package/src/Core/components/abstract/InlineComponent.js +5 -0
- package/src/Core/components/abstract/InlineRenderInlineChildren.js +63 -0
- package/src/Core/components/abstract/Input.js +192 -0
- package/src/Core/components/abstract/IntervalListComponent.js +218 -0
- package/src/Core/components/abstract/LineListComponent.js +114 -0
- package/src/Core/components/abstract/MathBaseOperator.js +631 -0
- package/src/Core/components/abstract/MathBaseOperatorOneInput.js +112 -0
- package/src/Core/components/abstract/PointListComponent.js +238 -0
- package/src/Core/components/abstract/SectioningComponent.js +1262 -0
- package/src/Core/components/abstract/SingleCharacterInline.js +23 -0
- package/src/Core/components/abstract/TextBaseOperatorOfMath.js +47 -0
- package/src/Core/components/abstract/TextOrInline.js +66 -0
- package/src/Core/components/abstract/VariableName.js +31 -0
- package/src/Core/components/abstract/VariableNameList.js +83 -0
- package/src/Core/components/abstract/VectorListComponent.js +235 -0
- package/src/Core/components/chemistry/Atom.js +910 -0
- package/src/Core/components/chemistry/ElectronConfiguration.js +36 -0
- package/src/Core/components/chemistry/Ion.js +684 -0
- package/src/Core/components/chemistry/IonicCompound.js +189 -0
- package/src/Core/components/chemistry/OrbitalDiagram.js +175 -0
- package/src/Core/components/chemistry/OrbitalDiagramInput.js +753 -0
- package/src/Core/components/chemistry/index.js +6 -0
- package/src/Core/components/commonsugar/breakstrings.js +627 -0
- package/src/Core/components/commonsugar/lists.js +177 -0
- package/src/Core/components/dynamicalSystems/CobwebPolyline.js +913 -0
- package/src/Core/components/dynamicalSystems/EquilibriumCurve.js +95 -0
- package/src/Core/components/dynamicalSystems/EquilibriumLine.js +93 -0
- package/src/Core/components/dynamicalSystems/EquilibriumPoint.js +93 -0
- package/src/Core/components/dynamicalSystems/ODESystem.js +943 -0
- package/src/Core/components/dynamicalSystems/index.js +5 -0
- package/src/Core/components/linearAlgebra/EigenDecomposition.js +294 -0
- package/src/Core/utils/array.js +30 -0
- package/src/Core/utils/booleanLogic.js +965 -0
- package/src/Core/utils/checkEquality.js +818 -0
- package/src/Core/utils/cid.js +29 -0
- package/src/Core/utils/componentInfoObjects.js +100 -0
- package/src/Core/utils/constraints.js +23 -0
- package/src/Core/utils/copy.js +572 -0
- package/src/Core/utils/deepFunctions.js +173 -0
- package/src/Core/utils/descendants.js +252 -0
- package/src/Core/utils/enumeration.js +234 -0
- package/src/Core/utils/feedback.js +84 -0
- package/src/Core/utils/function.js +1343 -0
- package/src/Core/utils/graphical.js +196 -0
- package/src/Core/utils/label.js +396 -0
- package/src/Core/utils/math.js +1056 -0
- package/src/Core/utils/naming.js +45 -0
- package/src/Core/utils/periodicSetEquality.js +403 -0
- package/src/Core/utils/randomNumbers.js +70 -0
- package/src/Core/utils/retrieveMedia.js +98 -0
- package/src/Core/utils/retrieveTextFile.js +140 -0
- package/src/Core/utils/returnAllPossibleVariants.js +73 -0
- package/src/Core/utils/rounding.js +316 -0
- package/src/Core/utils/sequence.js +754 -0
- package/src/Core/utils/serializedStateProcessing.js +4049 -0
- package/src/Core/utils/size.js +22 -0
- package/src/Core/utils/stateVariables.js +138 -0
- package/src/Core/utils/style.js +535 -0
- package/src/Core/utils/subset-of-reals.js +796 -0
- package/src/Core/utils/table.js +41 -0
- package/src/Core/utils/text.js +16 -0
- package/src/Core/utils/triggering.js +167 -0
- package/src/Core/utils/variants.js +477 -0
- package/src/DoenetML.css +308 -0
- package/src/DoenetML.jsx +201 -0
- package/src/Parser/doenet.grammar +90 -0
- package/src/Parser/doenet.js +33 -0
- package/src/Parser/doenet.terms.js +20 -0
- package/src/Parser/parser.js +266 -0
- package/src/Parser/tokens.js +129 -0
- package/src/Tools/CodeMirror.jsx +440 -0
- package/src/Tools/DarkmodeController.jsx +21 -0
- package/src/Tools/Footers/MathInputSelector.jsx +34 -0
- package/src/Tools/Footers/VirtualKeyboard.jsx +751 -0
- package/src/Tools/cypressTest/CypressTest.jsx +341 -0
- package/src/Tools/cypressTest/index.html +102 -0
- package/src/Tools/cypressTest/index.jsx +40 -0
- package/src/Viewer/ActivityViewer.jsx +1461 -0
- package/src/Viewer/PageViewer.jsx +1329 -0
- package/src/Viewer/renderers/alert.jsx +17 -0
- package/src/Viewer/renderers/angle.jsx +209 -0
- package/src/Viewer/renderers/answer.jsx +206 -0
- package/src/Viewer/renderers/asList.jsx +25 -0
- package/src/Viewer/renderers/blockQuote.jsx +41 -0
- package/src/Viewer/renderers/boolean.jsx +17 -0
- package/src/Viewer/renderers/booleanInput.css +105 -0
- package/src/Viewer/renderers/booleanInput.jsx +636 -0
- package/src/Viewer/renderers/button.jsx +369 -0
- package/src/Viewer/renderers/c.jsx +17 -0
- package/src/Viewer/renderers/callAction.jsx +18 -0
- package/src/Viewer/renderers/cell.jsx +59 -0
- package/src/Viewer/renderers/chart.jsx +83 -0
- package/src/Viewer/renderers/choiceInput.css +223 -0
- package/src/Viewer/renderers/choiceInput.jsx +535 -0
- package/src/Viewer/renderers/circle.jsx +990 -0
- package/src/Viewer/renderers/cobwebPolyline.jsx +442 -0
- package/src/Viewer/renderers/codeEditor.jsx +248 -0
- package/src/Viewer/renderers/codeViewer.jsx +105 -0
- package/src/Viewer/renderers/containerBlock.jsx +41 -0
- package/src/Viewer/renderers/containerInline.jsx +17 -0
- package/src/Viewer/renderers/contentBrowser.jsx +159 -0
- package/src/Viewer/renderers/contentPicker.jsx +160 -0
- package/src/Viewer/renderers/curve.jsx +1072 -0
- package/src/Viewer/renderers/ellipsis.jsx +17 -0
- package/src/Viewer/renderers/em.jsx +17 -0
- package/src/Viewer/renderers/embed.jsx +110 -0
- package/src/Viewer/renderers/feedback.jsx +74 -0
- package/src/Viewer/renderers/figure.jsx +131 -0
- package/src/Viewer/renderers/footnote.jsx +52 -0
- package/src/Viewer/renderers/graph.jsx +925 -0
- package/src/Viewer/renderers/hint.jsx +142 -0
- package/src/Viewer/renderers/image.jsx +581 -0
- package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs +2 -0
- package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs.map +1 -0
- package/src/Viewer/renderers/label.jsx +470 -0
- package/src/Viewer/renderers/legend.jsx +306 -0
- package/src/Viewer/renderers/line.jsx +511 -0
- package/src/Viewer/renderers/lineSegment.jsx +754 -0
- package/src/Viewer/renderers/list.jsx +111 -0
- package/src/Viewer/renderers/lq.jsx +12 -0
- package/src/Viewer/renderers/lsq.jsx +12 -0
- package/src/Viewer/renderers/math.jsx +582 -0
- package/src/Viewer/renderers/mathInput.css +10 -0
- package/src/Viewer/renderers/mathInput.jsx +425 -0
- package/src/Viewer/renderers/mathInputog.jsx +534 -0
- package/src/Viewer/renderers/mathList.jsx +39 -0
- package/src/Viewer/renderers/matrixInput.jsx +317 -0
- package/src/Viewer/renderers/mdash.jsx +12 -0
- package/src/Viewer/renderers/nbsp.jsx +12 -0
- package/src/Viewer/renderers/ndash.jsx +12 -0
- package/src/Viewer/renderers/number.jsx +454 -0
- package/src/Viewer/renderers/numberList.jsx +35 -0
- package/src/Viewer/renderers/orbitalDiagram.jsx +247 -0
- package/src/Viewer/renderers/orbitalDiagramInput.jsx +450 -0
- package/src/Viewer/renderers/p.jsx +38 -0
- package/src/Viewer/renderers/paginatorControls.jsx +41 -0
- package/src/Viewer/renderers/pegboard.jsx +239 -0
- package/src/Viewer/renderers/point.jsx +649 -0
- package/src/Viewer/renderers/polygon.jsx +612 -0
- package/src/Viewer/renderers/polyline.jsx +608 -0
- package/src/Viewer/renderers/pre.jsx +34 -0
- package/src/Viewer/renderers/q.jsx +17 -0
- package/src/Viewer/renderers/ray.jsx +410 -0
- package/src/Viewer/renderers/ref.jsx +149 -0
- package/src/Viewer/renderers/regionBetweenCurveXAxis.jsx +182 -0
- package/src/Viewer/renderers/renderDoenetML.jsx +56 -0
- package/src/Viewer/renderers/row.jsx +31 -0
- package/src/Viewer/renderers/rq.jsx +12 -0
- package/src/Viewer/renderers/rsq.jsx +12 -0
- package/src/Viewer/renderers/section.jsx +427 -0
- package/src/Viewer/renderers/sideBySide.jsx +80 -0
- package/src/Viewer/renderers/slider.jsx +800 -0
- package/src/Viewer/renderers/solution.jsx +134 -0
- package/src/Viewer/renderers/spreadsheet.jsx +83 -0
- package/src/Viewer/renderers/sq.jsx +17 -0
- package/src/Viewer/renderers/styles/global.css +14 -0
- package/src/Viewer/renderers/subsetOfRealsInput.jsx +392 -0
- package/src/Viewer/renderers/summaryStatistics.jsx +83 -0
- package/src/Viewer/renderers/table.jsx +78 -0
- package/src/Viewer/renderers/tabular.jsx +58 -0
- package/src/Viewer/renderers/tag.jsx +26 -0
- package/src/Viewer/renderers/text.jsx +439 -0
- package/src/Viewer/renderers/textInput.jsx +774 -0
- package/src/Viewer/renderers/textList.jsx +30 -0
- package/src/Viewer/renderers/triggerSet.jsx +52 -0
- package/src/Viewer/renderers/updateValue.jsx +30 -0
- package/src/Viewer/renderers/utils/css.js +13 -0
- package/src/Viewer/renderers/utils/graph.js +159 -0
- package/src/Viewer/renderers/utils/offGraphIndicators.js +91 -0
- package/src/Viewer/renderers/vector.jsx +678 -0
- package/src/Viewer/renderers/video.jsx +494 -0
- package/src/Viewer/useDoenetRenderer.jsx +128 -0
- package/src/main.jsx +16 -0
- package/src/media/fonts/files/open-sans-v18-latin-700.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-regular.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
- package/src/test/testCode.doenet +26 -0
- package/src/test/testViewer.jsx +158 -0
- package/src/uiComponents/ActionButton.jsx +157 -0
- package/src/uiComponents/ActionButtonGroup.jsx +93 -0
- package/src/uiComponents/Button.jsx +160 -0
- package/src/uiComponents/ButtonGroup.jsx +56 -0
- package/src/uiComponents/ToggleButton.jsx +194 -0
- package/src/uiComponents/ToggleButtonGroup.jsx +77 -0
- package/src/utils/activityUtils.js +713 -0
- package/src/utils/array.js +17 -0
- package/src/utils/cid.js +34 -0
- package/src/utils/componentInfoObjects.js +89 -0
- package/src/utils/deepFunctions.js +165 -0
- package/src/utils/enumeration.js +226 -0
- package/src/utils/math.js +624 -0
- package/src/utils/naming.js +44 -0
- package/src/utils/retrieveTextFile.js +156 -0
- package/src/utils/returnAllPossibleVariants.js +81 -0
- package/src/utils/sequence.js +715 -0
- package/src/utils/serialize.js +29 -0
- package/src/utils/serializedStateProcessing.js +2587 -0
- package/src/utils/subset-of-reals.js +783 -0
- package/src/utils/url.js +19 -0
- package/vite.config.js +14 -0
|
@@ -0,0 +1,3412 @@
|
|
|
1
|
+
import CompositeComponent from "./abstract/CompositeComponent";
|
|
2
|
+
import * as serializeFunctions from "../utils/serializedStateProcessing";
|
|
3
|
+
import {
|
|
4
|
+
convertAttributesForComponentType,
|
|
5
|
+
postProcessCopy,
|
|
6
|
+
verifyReplacementsMatchSpecifiedType,
|
|
7
|
+
} from "../utils/copy";
|
|
8
|
+
import { flattenDeep, flattenLevels } from "../utils/array";
|
|
9
|
+
import { getUniqueIdentifierFromBase } from "../utils/naming";
|
|
10
|
+
import { deepClone } from "../utils/deepFunctions";
|
|
11
|
+
|
|
12
|
+
export default class Copy extends CompositeComponent {
|
|
13
|
+
static componentType = "copy";
|
|
14
|
+
|
|
15
|
+
static assignNamesToReplacements = true;
|
|
16
|
+
|
|
17
|
+
static acceptTarget = true;
|
|
18
|
+
static acceptAnyAttribute = true;
|
|
19
|
+
|
|
20
|
+
static includeBlankStringChildren = true;
|
|
21
|
+
|
|
22
|
+
static stateVariableToEvaluateAfterReplacements =
|
|
23
|
+
"needsReplacementsUpdatedWhenStale";
|
|
24
|
+
|
|
25
|
+
static createAttributesObject() {
|
|
26
|
+
let attributes = super.createAttributesObject();
|
|
27
|
+
|
|
28
|
+
// delete off attributes from base component that should apply to replacements instead
|
|
29
|
+
// (using acceptAnyAttribute)
|
|
30
|
+
delete attributes.disabled;
|
|
31
|
+
delete attributes.modifyIndirectly;
|
|
32
|
+
delete attributes.fixed;
|
|
33
|
+
delete attributes.styleNumber;
|
|
34
|
+
delete attributes.isResponse;
|
|
35
|
+
delete attributes.hide;
|
|
36
|
+
|
|
37
|
+
attributes.assignNewNamespaces = {
|
|
38
|
+
createPrimitiveOfType: "boolean",
|
|
39
|
+
};
|
|
40
|
+
attributes.assignNamesSkip = {
|
|
41
|
+
createPrimitiveOfType: "number",
|
|
42
|
+
};
|
|
43
|
+
attributes.prop = {
|
|
44
|
+
createPrimitiveOfType: "string",
|
|
45
|
+
};
|
|
46
|
+
attributes.obtainPropFromComposite = {
|
|
47
|
+
createPrimitiveOfType: "boolean",
|
|
48
|
+
createStateVariable: "obtainPropFromComposite",
|
|
49
|
+
defaultValue: false,
|
|
50
|
+
public: true,
|
|
51
|
+
};
|
|
52
|
+
attributes.createComponentOfType = {
|
|
53
|
+
createPrimitiveOfType: "string",
|
|
54
|
+
};
|
|
55
|
+
attributes.numComponents = {
|
|
56
|
+
createPrimitiveOfType: "number",
|
|
57
|
+
};
|
|
58
|
+
attributes.componentIndex = {
|
|
59
|
+
createComponentOfType: "integer",
|
|
60
|
+
createStateVariable: "componentIndex",
|
|
61
|
+
defaultValue: null,
|
|
62
|
+
public: true,
|
|
63
|
+
};
|
|
64
|
+
attributes.sourceSubnames = {
|
|
65
|
+
createPrimitiveOfType: "stringArray",
|
|
66
|
+
createStateVariable: "targetSubnames",
|
|
67
|
+
defaultValue: null,
|
|
68
|
+
public: true,
|
|
69
|
+
};
|
|
70
|
+
attributes.sourceSubnamesComponentIndex = {
|
|
71
|
+
createComponentOfType: "numberList",
|
|
72
|
+
createStateVariable: "targetSubnamesComponentIndex",
|
|
73
|
+
defaultValue: null,
|
|
74
|
+
public: true,
|
|
75
|
+
};
|
|
76
|
+
attributes.propIndex = {
|
|
77
|
+
createComponentOfType: "numberList",
|
|
78
|
+
createStateVariable: "propIndex",
|
|
79
|
+
defaultValue: null,
|
|
80
|
+
public: true,
|
|
81
|
+
};
|
|
82
|
+
attributes.uri = {
|
|
83
|
+
createPrimitiveOfType: "string",
|
|
84
|
+
createStateVariable: "uri",
|
|
85
|
+
defaultValue: null,
|
|
86
|
+
public: true,
|
|
87
|
+
};
|
|
88
|
+
attributes.sourceAttributesToIgnore = {
|
|
89
|
+
createPrimitiveOfType: "stringArray",
|
|
90
|
+
createStateVariable: "sourceAttributesToIgnore",
|
|
91
|
+
defaultValue: ["isResponse"],
|
|
92
|
+
public: true,
|
|
93
|
+
};
|
|
94
|
+
attributes.link = {
|
|
95
|
+
createPrimitiveOfType: "boolean",
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Note: only implemented with no wrapping components
|
|
99
|
+
attributes.removeEmptyArrayEntries = {
|
|
100
|
+
createPrimitiveOfType: "boolean",
|
|
101
|
+
createStateVariable: "removeEmptyArrayEntries",
|
|
102
|
+
defaultValue: false,
|
|
103
|
+
};
|
|
104
|
+
return attributes;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static keepChildrenSerialized({ serializedComponent }) {
|
|
108
|
+
if (serializedComponent.children === undefined) {
|
|
109
|
+
return [];
|
|
110
|
+
} else {
|
|
111
|
+
return Object.keys(serializedComponent.children);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static returnStateVariableDefinitions() {
|
|
116
|
+
let stateVariableDefinitions = super.returnStateVariableDefinitions();
|
|
117
|
+
|
|
118
|
+
stateVariableDefinitions.target = {
|
|
119
|
+
returnDependencies: () => ({
|
|
120
|
+
target: {
|
|
121
|
+
dependencyType: "doenetAttribute",
|
|
122
|
+
attributeName: "target",
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
125
|
+
definition: ({ dependencyValues }) => ({
|
|
126
|
+
setValue: { target: dependencyValues.target },
|
|
127
|
+
}),
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
stateVariableDefinitions.targetSourcesName = {
|
|
131
|
+
additionalStateVariablesDefined: [
|
|
132
|
+
{
|
|
133
|
+
variableName: "sourcesChildNumber",
|
|
134
|
+
hasEssential: true,
|
|
135
|
+
shadowVariable: true,
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
stateVariablesDeterminingDependencies: ["target"],
|
|
139
|
+
determineDependenciesImmediately: true,
|
|
140
|
+
hasEssential: true,
|
|
141
|
+
shadowVariable: true,
|
|
142
|
+
returnDependencies: function ({ stateValues, sharedParameters }) {
|
|
143
|
+
let sourceNameMappings = sharedParameters.sourceNameMappings;
|
|
144
|
+
if (!sourceNameMappings) {
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let theMapping = sourceNameMappings[stateValues.target];
|
|
149
|
+
if (!theMapping) {
|
|
150
|
+
return {};
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
targetSourcesName: {
|
|
154
|
+
dependencyType: "value",
|
|
155
|
+
value: theMapping.name,
|
|
156
|
+
},
|
|
157
|
+
sourcesChildNumber: {
|
|
158
|
+
dependencyType: "value",
|
|
159
|
+
value: theMapping.childNumber,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
},
|
|
163
|
+
definition: function ({ dependencyValues }) {
|
|
164
|
+
let targetSourcesName = dependencyValues.targetSourcesName;
|
|
165
|
+
let sourcesChildNumber = dependencyValues.sourcesChildNumber;
|
|
166
|
+
if (!targetSourcesName) {
|
|
167
|
+
targetSourcesName = null;
|
|
168
|
+
sourcesChildNumber = null;
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
setValue: { targetSourcesName, sourcesChildNumber },
|
|
172
|
+
setEssentialValue: { targetSourcesName, sourcesChildNumber },
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
stateVariableDefinitions.targetSources = {
|
|
178
|
+
stateVariablesDeterminingDependencies: ["targetSourcesName"],
|
|
179
|
+
determineDependenciesImmediately: true,
|
|
180
|
+
returnDependencies({ stateValues }) {
|
|
181
|
+
if (!stateValues.targetSourcesName) {
|
|
182
|
+
return {};
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
targetSourcesComponent: {
|
|
186
|
+
dependencyType: "componentIdentity",
|
|
187
|
+
componentName: stateValues.targetSourcesName,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
definition: function ({ dependencyValues }) {
|
|
192
|
+
let targetSources = dependencyValues.targetSourcesComponent;
|
|
193
|
+
if (!targetSources) {
|
|
194
|
+
targetSources = null;
|
|
195
|
+
}
|
|
196
|
+
return { setValue: { targetSources } };
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
stateVariableDefinitions.sourceIndex = {
|
|
201
|
+
stateVariablesDeterminingDependencies: ["target"],
|
|
202
|
+
determineDependenciesImmediately: true,
|
|
203
|
+
hasEssential: true,
|
|
204
|
+
shadowVariable: true,
|
|
205
|
+
returnDependencies: function ({ stateValues, sharedParameters }) {
|
|
206
|
+
let sourceIndexMappings = sharedParameters.sourceIndexMappings;
|
|
207
|
+
if (!sourceIndexMappings) {
|
|
208
|
+
return {};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let theMapping = sourceIndexMappings[stateValues.target];
|
|
212
|
+
if (theMapping === undefined) {
|
|
213
|
+
return {};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
sourceIndex: {
|
|
218
|
+
dependencyType: "value",
|
|
219
|
+
value: theMapping,
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
},
|
|
223
|
+
definition: function ({ dependencyValues }) {
|
|
224
|
+
let sourceIndex = dependencyValues.sourceIndex;
|
|
225
|
+
if (sourceIndex === undefined) {
|
|
226
|
+
sourceIndex = null;
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
setValue: { sourceIndex },
|
|
230
|
+
setEssentialValue: { sourceIndex },
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
stateVariableDefinitions.targetComponent = {
|
|
236
|
+
shadowVariable: true,
|
|
237
|
+
stateVariablesDeterminingDependencies: ["targetSources", "sourceIndex"],
|
|
238
|
+
determineDependenciesImmediately: true,
|
|
239
|
+
returnDependencies({ stateValues }) {
|
|
240
|
+
if (stateValues.sourceIndex !== null) {
|
|
241
|
+
return {};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (stateValues.targetSources !== null) {
|
|
245
|
+
return {
|
|
246
|
+
targetSourcesChildren: {
|
|
247
|
+
dependencyType: "stateVariable",
|
|
248
|
+
componentName: stateValues.targetSources.componentName,
|
|
249
|
+
variableName: "childIdentities",
|
|
250
|
+
},
|
|
251
|
+
sourcesChildNumber: {
|
|
252
|
+
dependencyType: "stateVariable",
|
|
253
|
+
variableName: "sourcesChildNumber",
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
targetComponent: {
|
|
260
|
+
dependencyType: "targetComponent",
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
},
|
|
264
|
+
definition: function ({ dependencyValues }) {
|
|
265
|
+
let targetComponent = null;
|
|
266
|
+
if (dependencyValues.targetSourcesChildren) {
|
|
267
|
+
targetComponent =
|
|
268
|
+
dependencyValues.targetSourcesChildren[
|
|
269
|
+
dependencyValues.sourcesChildNumber
|
|
270
|
+
];
|
|
271
|
+
if (!targetComponent) {
|
|
272
|
+
targetComponent = null;
|
|
273
|
+
}
|
|
274
|
+
} else if (dependencyValues.targetComponent) {
|
|
275
|
+
targetComponent = dependencyValues.targetComponent;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return {
|
|
279
|
+
setValue: { targetComponent },
|
|
280
|
+
};
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
stateVariableDefinitions.targetInactive = {
|
|
285
|
+
stateVariablesDeterminingDependencies: ["targetComponent"],
|
|
286
|
+
returnDependencies({ stateValues }) {
|
|
287
|
+
if (stateValues.targetComponent) {
|
|
288
|
+
return {
|
|
289
|
+
targetIsInactiveCompositeReplacement: {
|
|
290
|
+
dependencyType: "stateVariable",
|
|
291
|
+
componentName: stateValues.targetComponent.componentName,
|
|
292
|
+
variableName: "isInactiveCompositeReplacement",
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
} else {
|
|
296
|
+
return {};
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
definition: function ({ dependencyValues }) {
|
|
300
|
+
return {
|
|
301
|
+
setValue: {
|
|
302
|
+
targetInactive: Boolean(
|
|
303
|
+
dependencyValues.targetIsInactiveCompositeReplacement,
|
|
304
|
+
),
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
stateVariableDefinitions.cid = {
|
|
311
|
+
additionalStateVariablesDefined: ["doenetId"],
|
|
312
|
+
returnDependencies: () => ({
|
|
313
|
+
uri: {
|
|
314
|
+
dependencyType: "stateVariable",
|
|
315
|
+
variableName: "uri",
|
|
316
|
+
},
|
|
317
|
+
}),
|
|
318
|
+
definition: function ({ dependencyValues }) {
|
|
319
|
+
if (
|
|
320
|
+
!dependencyValues.uri ||
|
|
321
|
+
dependencyValues.uri.substring(0, 7).toLowerCase() !== "doenet:"
|
|
322
|
+
) {
|
|
323
|
+
return {
|
|
324
|
+
setValue: { cid: null, doenetId: null },
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let cid = null,
|
|
329
|
+
doenetId = null;
|
|
330
|
+
|
|
331
|
+
let result = dependencyValues.uri.match(/[:&]cid=([^&]+)/i);
|
|
332
|
+
if (result) {
|
|
333
|
+
cid = result[1];
|
|
334
|
+
}
|
|
335
|
+
result = dependencyValues.uri.match(/[:&]doenetid=([^&]+)/i);
|
|
336
|
+
if (result) {
|
|
337
|
+
doenetId = result[1];
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return { setValue: { cid, doenetId } };
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
stateVariableDefinitions.serializedComponentsForCid = {
|
|
345
|
+
returnDependencies: () => ({
|
|
346
|
+
cid: {
|
|
347
|
+
dependencyType: "stateVariable",
|
|
348
|
+
variableName: "cid",
|
|
349
|
+
},
|
|
350
|
+
serializedChildren: {
|
|
351
|
+
dependencyType: "serializedChildren",
|
|
352
|
+
doNotProxy: true,
|
|
353
|
+
},
|
|
354
|
+
}),
|
|
355
|
+
definition: function ({ dependencyValues }) {
|
|
356
|
+
if (!dependencyValues.cid) {
|
|
357
|
+
return {
|
|
358
|
+
setValue: { serializedComponentsForCid: null },
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
if (!(dependencyValues.serializedChildren?.length > 0)) {
|
|
362
|
+
return {
|
|
363
|
+
setValue: { serializedComponentsForCid: null },
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
setValue: {
|
|
369
|
+
serializedComponentsForCid: dependencyValues.serializedChildren,
|
|
370
|
+
},
|
|
371
|
+
};
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
stateVariableDefinitions.propName = {
|
|
376
|
+
shadowVariable: true,
|
|
377
|
+
returnDependencies: () => ({
|
|
378
|
+
propName: {
|
|
379
|
+
dependencyType: "attributePrimitive",
|
|
380
|
+
attributeName: "prop",
|
|
381
|
+
},
|
|
382
|
+
}),
|
|
383
|
+
definition: function ({ dependencyValues }) {
|
|
384
|
+
return { setValue: { propName: dependencyValues.propName } };
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
stateVariableDefinitions.isPlainMacro = {
|
|
389
|
+
returnDependencies: () => ({
|
|
390
|
+
isPlainMacro: {
|
|
391
|
+
dependencyType: "doenetAttribute",
|
|
392
|
+
attributeName: "isPlainMacro",
|
|
393
|
+
},
|
|
394
|
+
targetComponent: {
|
|
395
|
+
dependencyType: "stateVariable",
|
|
396
|
+
variableName: "targetComponent",
|
|
397
|
+
},
|
|
398
|
+
typeAttr: {
|
|
399
|
+
dependencyType: "attributePrimitive",
|
|
400
|
+
attributeName: "createComponentOfType",
|
|
401
|
+
},
|
|
402
|
+
targetSubnames: {
|
|
403
|
+
dependencyType: "stateVariable",
|
|
404
|
+
variableName: "targetSubnames",
|
|
405
|
+
},
|
|
406
|
+
}),
|
|
407
|
+
definition: function ({ dependencyValues, componentInfoObjects }) {
|
|
408
|
+
let isPlainMacro =
|
|
409
|
+
dependencyValues.isPlainMacro &&
|
|
410
|
+
(!componentInfoObjects.isCompositeComponent({
|
|
411
|
+
componentType: dependencyValues.targetComponent?.componentType,
|
|
412
|
+
}) ||
|
|
413
|
+
dependencyValues.targetSubnames);
|
|
414
|
+
|
|
415
|
+
if (isPlainMacro && dependencyValues.typeAttr) {
|
|
416
|
+
// typically, if specify createComponentOfType (i.e., typeAttr is defined)
|
|
417
|
+
// then we wouldn't have a plain macro
|
|
418
|
+
// However, if we specified a different componentType
|
|
419
|
+
// and the variable for the plain macro is that componentType (or its undefined)
|
|
420
|
+
// then we'll keep it as a plain macro
|
|
421
|
+
|
|
422
|
+
isPlainMacro = false;
|
|
423
|
+
|
|
424
|
+
let componentTypeFromAttr =
|
|
425
|
+
componentInfoObjects.componentTypeLowerCaseMapping[
|
|
426
|
+
dependencyValues.typeAttr.toLowerCase()
|
|
427
|
+
];
|
|
428
|
+
|
|
429
|
+
let targetClass =
|
|
430
|
+
componentInfoObjects.allComponentClasses[
|
|
431
|
+
dependencyValues.targetComponent?.componentType
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
if (targetClass) {
|
|
435
|
+
let varInfo =
|
|
436
|
+
componentInfoObjects.publicStateVariableInfo[
|
|
437
|
+
targetClass.componentType
|
|
438
|
+
].stateVariableDescriptions[targetClass.variableForPlainMacro];
|
|
439
|
+
|
|
440
|
+
if (
|
|
441
|
+
componentTypeFromAttr !== targetClass.componentType &&
|
|
442
|
+
varInfo &&
|
|
443
|
+
(varInfo.createComponentOfType === undefined ||
|
|
444
|
+
varInfo.createComponentOfType === componentTypeFromAttr)
|
|
445
|
+
) {
|
|
446
|
+
isPlainMacro = true;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return { setValue: { isPlainMacro } };
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
stateVariableDefinitions.isPlainCopy = {
|
|
456
|
+
returnDependencies: () => ({
|
|
457
|
+
isPlainCopy: {
|
|
458
|
+
dependencyType: "doenetAttribute",
|
|
459
|
+
attributeName: "isPlainCopy",
|
|
460
|
+
},
|
|
461
|
+
targetComponent: {
|
|
462
|
+
dependencyType: "stateVariable",
|
|
463
|
+
variableName: "targetComponent",
|
|
464
|
+
},
|
|
465
|
+
typeAttr: {
|
|
466
|
+
dependencyType: "attributePrimitive",
|
|
467
|
+
attributeName: "createComponentOfType",
|
|
468
|
+
},
|
|
469
|
+
targetSubnames: {
|
|
470
|
+
dependencyType: "stateVariable",
|
|
471
|
+
variableName: "targetSubnames",
|
|
472
|
+
},
|
|
473
|
+
}),
|
|
474
|
+
definition: function ({ dependencyValues, componentInfoObjects }) {
|
|
475
|
+
let isPlainCopy =
|
|
476
|
+
dependencyValues.isPlainCopy &&
|
|
477
|
+
(!componentInfoObjects.isCompositeComponent({
|
|
478
|
+
componentType: dependencyValues.targetComponent?.componentType,
|
|
479
|
+
}) ||
|
|
480
|
+
dependencyValues.targetSubnames);
|
|
481
|
+
|
|
482
|
+
if (isPlainCopy && dependencyValues.typeAttr) {
|
|
483
|
+
// typically, if specify createComponentOfType (i.e., typeAttr is defined)
|
|
484
|
+
// then we wouldn't have a plain copy
|
|
485
|
+
// However, if we specified a different componentType
|
|
486
|
+
// and the variable for the plain copy is that componentType (or its undefined)
|
|
487
|
+
// then we'll keep it as a plain copy
|
|
488
|
+
|
|
489
|
+
isPlainCopy = false;
|
|
490
|
+
|
|
491
|
+
let componentTypeFromAttr =
|
|
492
|
+
componentInfoObjects.componentTypeLowerCaseMapping[
|
|
493
|
+
dependencyValues.typeAttr.toLowerCase()
|
|
494
|
+
];
|
|
495
|
+
|
|
496
|
+
let targetClass =
|
|
497
|
+
componentInfoObjects.allComponentClasses[
|
|
498
|
+
dependencyValues.targetComponent?.componentType
|
|
499
|
+
];
|
|
500
|
+
|
|
501
|
+
if (targetClass) {
|
|
502
|
+
let varInfo =
|
|
503
|
+
componentInfoObjects.publicStateVariableInfo[
|
|
504
|
+
targetClass.componentType
|
|
505
|
+
].stateVariableDescriptions[targetClass.variableForPlainCopy];
|
|
506
|
+
|
|
507
|
+
if (
|
|
508
|
+
componentTypeFromAttr !== targetClass.componentType &&
|
|
509
|
+
varInfo &&
|
|
510
|
+
(varInfo.createComponentOfType === undefined ||
|
|
511
|
+
varInfo.createComponentOfType === componentTypeFromAttr)
|
|
512
|
+
) {
|
|
513
|
+
isPlainCopy = true;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return { setValue: { isPlainCopy } };
|
|
519
|
+
},
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
stateVariableDefinitions.linkAttrForDetermineDeps = {
|
|
523
|
+
returnDependencies: () => ({
|
|
524
|
+
linkAttr: {
|
|
525
|
+
dependencyType: "attributePrimitive",
|
|
526
|
+
attributeName: "link",
|
|
527
|
+
},
|
|
528
|
+
}),
|
|
529
|
+
definition({ dependencyValues }) {
|
|
530
|
+
let linkAttrForDetermineDeps;
|
|
531
|
+
if (dependencyValues.linkAttr === null) {
|
|
532
|
+
linkAttrForDetermineDeps = true;
|
|
533
|
+
} else {
|
|
534
|
+
linkAttrForDetermineDeps = dependencyValues.linkAttr;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return { setValue: { linkAttrForDetermineDeps } };
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
stateVariableDefinitions.replacementSourceIdentities = {
|
|
542
|
+
stateVariablesDeterminingDependencies: [
|
|
543
|
+
"targetComponent",
|
|
544
|
+
"componentIndex",
|
|
545
|
+
"propName",
|
|
546
|
+
"targetSubnames",
|
|
547
|
+
"targetSubnamesComponentIndex",
|
|
548
|
+
"obtainPropFromComposite",
|
|
549
|
+
"linkAttrForDetermineDeps",
|
|
550
|
+
],
|
|
551
|
+
additionalStateVariablesDefined: ["addLevelToAssignNames"],
|
|
552
|
+
returnDependencies: function ({ stateValues, componentInfoObjects }) {
|
|
553
|
+
let dependencies = {};
|
|
554
|
+
|
|
555
|
+
let addLevelToAssignNames = false;
|
|
556
|
+
let useReplacements = false;
|
|
557
|
+
|
|
558
|
+
if (stateValues.targetComponent !== null) {
|
|
559
|
+
if (
|
|
560
|
+
componentInfoObjects.isCompositeComponent({
|
|
561
|
+
componentType: stateValues.targetComponent.componentType,
|
|
562
|
+
includeNonStandard: false,
|
|
563
|
+
}) &&
|
|
564
|
+
!(stateValues.propName && stateValues.obtainPropFromComposite)
|
|
565
|
+
) {
|
|
566
|
+
if (stateValues.linkAttrForDetermineDeps) {
|
|
567
|
+
useReplacements = true;
|
|
568
|
+
|
|
569
|
+
let targetSubnamesComponentIndex =
|
|
570
|
+
stateValues.targetSubnamesComponentIndex;
|
|
571
|
+
if (targetSubnamesComponentIndex) {
|
|
572
|
+
targetSubnamesComponentIndex = [
|
|
573
|
+
...targetSubnamesComponentIndex,
|
|
574
|
+
];
|
|
575
|
+
}
|
|
576
|
+
dependencies.targets = {
|
|
577
|
+
dependencyType: "replacement",
|
|
578
|
+
compositeName: stateValues.targetComponent.componentName,
|
|
579
|
+
recursive: true,
|
|
580
|
+
componentIndex: stateValues.componentIndex,
|
|
581
|
+
targetSubnames: stateValues.targetSubnames,
|
|
582
|
+
targetSubnamesComponentIndex,
|
|
583
|
+
};
|
|
584
|
+
} else {
|
|
585
|
+
addLevelToAssignNames = true;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (
|
|
590
|
+
!useReplacements &&
|
|
591
|
+
(stateValues.componentIndex === null ||
|
|
592
|
+
stateValues.componentIndex === 1)
|
|
593
|
+
) {
|
|
594
|
+
// if we don't have a composite, componentIndex can only match if it is 1
|
|
595
|
+
dependencies.targets = {
|
|
596
|
+
dependencyType: "stateVariable",
|
|
597
|
+
variableName: "targetComponent",
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
dependencies.addLevelToAssignNames = {
|
|
603
|
+
dependencyType: "value",
|
|
604
|
+
value: addLevelToAssignNames,
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
return dependencies;
|
|
608
|
+
},
|
|
609
|
+
definition({ dependencyValues }) {
|
|
610
|
+
let replacementSourceIdentities = null;
|
|
611
|
+
if (dependencyValues.targets) {
|
|
612
|
+
replacementSourceIdentities = dependencyValues.targets;
|
|
613
|
+
if (!Array.isArray(replacementSourceIdentities)) {
|
|
614
|
+
replacementSourceIdentities = [replacementSourceIdentities];
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return {
|
|
618
|
+
setValue: {
|
|
619
|
+
replacementSourceIdentities,
|
|
620
|
+
addLevelToAssignNames: dependencyValues.addLevelToAssignNames,
|
|
621
|
+
},
|
|
622
|
+
};
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
// only reason for replacementSources state variable
|
|
627
|
+
// is to create any array entry state variables from prop
|
|
628
|
+
// when resolve determineDependencies
|
|
629
|
+
stateVariableDefinitions.replacementSources = {
|
|
630
|
+
stateVariablesDeterminingDependencies: [
|
|
631
|
+
"replacementSourceIdentities",
|
|
632
|
+
"propName",
|
|
633
|
+
"propIndex",
|
|
634
|
+
"isPlainMacro",
|
|
635
|
+
"isPlainCopy",
|
|
636
|
+
],
|
|
637
|
+
additionalStateVariablesDefined: ["effectivePropNameBySource"],
|
|
638
|
+
returnDependencies: function ({ stateValues, componentInfoObjects }) {
|
|
639
|
+
let dependencies = {
|
|
640
|
+
replacementSourceIdentities: {
|
|
641
|
+
dependencyType: "stateVariable",
|
|
642
|
+
variableName: "replacementSourceIdentities",
|
|
643
|
+
},
|
|
644
|
+
propIndex: {
|
|
645
|
+
dependencyType: "stateVariable",
|
|
646
|
+
variableName: "propIndex",
|
|
647
|
+
},
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
if (!stateValues.propName && stateValues.propIndex !== null) {
|
|
651
|
+
throw Error(
|
|
652
|
+
`You cannot specify a propIndex without specifying a prop.`,
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (stateValues.replacementSourceIdentities !== null) {
|
|
657
|
+
for (let [
|
|
658
|
+
ind,
|
|
659
|
+
source,
|
|
660
|
+
] of stateValues.replacementSourceIdentities.entries()) {
|
|
661
|
+
let thisPropName = stateValues.propName;
|
|
662
|
+
|
|
663
|
+
if (stateValues.isPlainMacro) {
|
|
664
|
+
thisPropName =
|
|
665
|
+
componentInfoObjects.allComponentClasses[source.componentType]
|
|
666
|
+
.variableForPlainMacro;
|
|
667
|
+
} else if (stateValues.isPlainCopy) {
|
|
668
|
+
thisPropName =
|
|
669
|
+
componentInfoObjects.allComponentClasses[source.componentType]
|
|
670
|
+
.variableForPlainCopy;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
let thisTarget;
|
|
674
|
+
|
|
675
|
+
if (thisPropName) {
|
|
676
|
+
dependencies["propName" + ind] = {
|
|
677
|
+
dependencyType: "value",
|
|
678
|
+
value: thisPropName,
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
let propIndex = stateValues.propIndex;
|
|
682
|
+
if (propIndex) {
|
|
683
|
+
// make propIndex be a shallow copy
|
|
684
|
+
// so that can detect if it changed
|
|
685
|
+
// when update dependencies
|
|
686
|
+
propIndex = [...propIndex];
|
|
687
|
+
}
|
|
688
|
+
thisTarget = {
|
|
689
|
+
dependencyType: "stateVariable",
|
|
690
|
+
componentName: source.componentName,
|
|
691
|
+
variableName: thisPropName,
|
|
692
|
+
returnAsComponentObject: true,
|
|
693
|
+
variablesOptional: true,
|
|
694
|
+
propIndex,
|
|
695
|
+
caseInsensitiveVariableMatch: true,
|
|
696
|
+
publicStateVariablesOnly: true,
|
|
697
|
+
useMappedVariableNames: true,
|
|
698
|
+
};
|
|
699
|
+
} else {
|
|
700
|
+
thisTarget = {
|
|
701
|
+
dependencyType: "componentIdentity",
|
|
702
|
+
componentName: source.componentName,
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
dependencies["target" + ind] = thisTarget;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
return dependencies;
|
|
711
|
+
},
|
|
712
|
+
definition({ dependencyValues }) {
|
|
713
|
+
let replacementSources = null;
|
|
714
|
+
let effectivePropNameBySource = null;
|
|
715
|
+
|
|
716
|
+
if (dependencyValues.replacementSourceIdentities !== null) {
|
|
717
|
+
replacementSources = [];
|
|
718
|
+
effectivePropNameBySource = [];
|
|
719
|
+
|
|
720
|
+
for (let ind in dependencyValues.replacementSourceIdentities) {
|
|
721
|
+
let targetDep = dependencyValues["target" + ind];
|
|
722
|
+
if (targetDep) {
|
|
723
|
+
replacementSources.push(targetDep);
|
|
724
|
+
|
|
725
|
+
let propName;
|
|
726
|
+
if (targetDep.stateValues) {
|
|
727
|
+
propName = Object.keys(targetDep.stateValues)[0];
|
|
728
|
+
}
|
|
729
|
+
if (!propName && dependencyValues["propName" + ind]) {
|
|
730
|
+
// a propName was specified, but it just wasn't found
|
|
731
|
+
propName = "__prop_name_not_found";
|
|
732
|
+
}
|
|
733
|
+
effectivePropNameBySource.push(propName);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
return { setValue: { replacementSources, effectivePropNameBySource } };
|
|
739
|
+
},
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
stateVariableDefinitions.numComponentsSpecified = {
|
|
743
|
+
returnDependencies: () => ({
|
|
744
|
+
numComponentsAttr: {
|
|
745
|
+
dependencyType: "attributePrimitive",
|
|
746
|
+
attributeName: "numComponents",
|
|
747
|
+
},
|
|
748
|
+
typeAttr: {
|
|
749
|
+
dependencyType: "attributePrimitive",
|
|
750
|
+
attributeName: "createComponentOfType",
|
|
751
|
+
},
|
|
752
|
+
}),
|
|
753
|
+
definition({ dependencyValues, componentInfoObjects }) {
|
|
754
|
+
let numComponentsSpecified;
|
|
755
|
+
|
|
756
|
+
if (dependencyValues.typeAttr) {
|
|
757
|
+
let componentType =
|
|
758
|
+
componentInfoObjects.componentTypeLowerCaseMapping[
|
|
759
|
+
dependencyValues.typeAttr.toLowerCase()
|
|
760
|
+
];
|
|
761
|
+
|
|
762
|
+
if (!(componentType in componentInfoObjects.allComponentClasses)) {
|
|
763
|
+
throw Error(
|
|
764
|
+
`Invalid componentType ${dependencyValues.typeAttr} of copy.`,
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
if (dependencyValues.numComponentsAttr !== null) {
|
|
768
|
+
numComponentsSpecified = dependencyValues.numComponentsAttr;
|
|
769
|
+
} else {
|
|
770
|
+
numComponentsSpecified = 1;
|
|
771
|
+
}
|
|
772
|
+
} else if (dependencyValues.numComponentsAttr !== null) {
|
|
773
|
+
throw Error(
|
|
774
|
+
`You must specify createComponentOfType when specifying numComponents for a copy.`,
|
|
775
|
+
);
|
|
776
|
+
} else {
|
|
777
|
+
numComponentsSpecified = null;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
return { setValue: { numComponentsSpecified } };
|
|
781
|
+
},
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
stateVariableDefinitions.link = {
|
|
785
|
+
returnDependencies: () => ({
|
|
786
|
+
linkAttr: {
|
|
787
|
+
dependencyType: "attributePrimitive",
|
|
788
|
+
attributeName: "link",
|
|
789
|
+
},
|
|
790
|
+
serializedComponentsForCid: {
|
|
791
|
+
dependencyType: "stateVariable",
|
|
792
|
+
variableName: "serializedComponentsForCid",
|
|
793
|
+
},
|
|
794
|
+
replacementSourceIdentities: {
|
|
795
|
+
dependencyType: "stateVariable",
|
|
796
|
+
variableName: "replacementSourceIdentities",
|
|
797
|
+
},
|
|
798
|
+
}),
|
|
799
|
+
definition({ dependencyValues, componentInfoObjects }) {
|
|
800
|
+
let link;
|
|
801
|
+
if (dependencyValues.linkAttr === null) {
|
|
802
|
+
if (
|
|
803
|
+
dependencyValues.serializedComponentsForCid ||
|
|
804
|
+
(dependencyValues.replacementSourceIdentities &&
|
|
805
|
+
dependencyValues.replacementSourceIdentities.some((x) =>
|
|
806
|
+
componentInfoObjects.isInheritedComponentType({
|
|
807
|
+
inheritedComponentType: x.componentType,
|
|
808
|
+
baseComponentType: "module",
|
|
809
|
+
}),
|
|
810
|
+
))
|
|
811
|
+
) {
|
|
812
|
+
link = false;
|
|
813
|
+
} else {
|
|
814
|
+
link = true;
|
|
815
|
+
}
|
|
816
|
+
} else {
|
|
817
|
+
link = dependencyValues.linkAttr !== false;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return { setValue: { link } };
|
|
821
|
+
},
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
stateVariableDefinitions.readyToExpandWhenResolved = {
|
|
825
|
+
stateVariablesDeterminingDependencies: [
|
|
826
|
+
"targetComponent",
|
|
827
|
+
"propName",
|
|
828
|
+
"obtainPropFromComposite",
|
|
829
|
+
"link",
|
|
830
|
+
],
|
|
831
|
+
returnDependencies({ stateValues, componentInfoObjects }) {
|
|
832
|
+
let dependencies = {
|
|
833
|
+
targetComponent: {
|
|
834
|
+
dependencyType: "stateVariable",
|
|
835
|
+
variableName: "targetComponent",
|
|
836
|
+
},
|
|
837
|
+
needsReplacementsUpdatedWhenStale: {
|
|
838
|
+
dependencyType: "stateVariable",
|
|
839
|
+
variableName: "needsReplacementsUpdatedWhenStale",
|
|
840
|
+
},
|
|
841
|
+
// replacementSources: {
|
|
842
|
+
// dependencyType: "stateVariable",
|
|
843
|
+
// variableName: "replacementSources",
|
|
844
|
+
// },
|
|
845
|
+
serializedComponentsForCid: {
|
|
846
|
+
dependencyType: "stateVariable",
|
|
847
|
+
variableName: "serializedComponentsForCid",
|
|
848
|
+
},
|
|
849
|
+
link: {
|
|
850
|
+
dependencyType: "stateVariable",
|
|
851
|
+
variableName: "link",
|
|
852
|
+
},
|
|
853
|
+
// propName: {
|
|
854
|
+
// dependencyType: "stateVariable",
|
|
855
|
+
// variableName: "propName",
|
|
856
|
+
// },
|
|
857
|
+
};
|
|
858
|
+
if (
|
|
859
|
+
stateValues.targetComponent &&
|
|
860
|
+
componentInfoObjects.isCompositeComponent({
|
|
861
|
+
componentType: stateValues.targetComponent.componentType,
|
|
862
|
+
includeNonStandard: false,
|
|
863
|
+
}) &&
|
|
864
|
+
!(stateValues.propName && stateValues.obtainPropFromComposite)
|
|
865
|
+
) {
|
|
866
|
+
dependencies.targetReadyToExpandWhenResolved = {
|
|
867
|
+
dependencyType: "stateVariable",
|
|
868
|
+
componentName: stateValues.targetComponent.componentName,
|
|
869
|
+
variableName: "readyToExpandWhenResolved",
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// since will be creating complete replacement when expand,
|
|
874
|
+
// make sure all replacement sources are resolved
|
|
875
|
+
if (!stateValues.link) {
|
|
876
|
+
dependencies.replacementSources = {
|
|
877
|
+
dependencyType: "stateVariable",
|
|
878
|
+
variableName: "replacementSources",
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
return dependencies;
|
|
883
|
+
},
|
|
884
|
+
definition() {
|
|
885
|
+
return { setValue: { readyToExpandWhenResolved: true } };
|
|
886
|
+
},
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
stateVariableDefinitions.needsReplacementsUpdatedWhenStale = {
|
|
890
|
+
stateVariablesDeterminingDependencies: [
|
|
891
|
+
"targetComponent",
|
|
892
|
+
"replacementSourceIdentities",
|
|
893
|
+
"effectivePropNameBySource",
|
|
894
|
+
"propName",
|
|
895
|
+
"obtainPropFromComposite",
|
|
896
|
+
"link",
|
|
897
|
+
"removeEmptyArrayEntries",
|
|
898
|
+
],
|
|
899
|
+
returnDependencies: function ({ stateValues, componentInfoObjects }) {
|
|
900
|
+
// if don't link, never update replacements
|
|
901
|
+
if (!stateValues.link) {
|
|
902
|
+
return {};
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
let dependencies = {
|
|
906
|
+
targetComponent: {
|
|
907
|
+
dependencyType: "stateVariable",
|
|
908
|
+
variableName: "targetComponent",
|
|
909
|
+
},
|
|
910
|
+
targetInactive: {
|
|
911
|
+
dependencyType: "stateVariable",
|
|
912
|
+
variableName: "targetInactive",
|
|
913
|
+
},
|
|
914
|
+
replacementSourceIdentities: {
|
|
915
|
+
dependencyType: "stateVariable",
|
|
916
|
+
variableName: "replacementSourceIdentities",
|
|
917
|
+
},
|
|
918
|
+
propIndex: {
|
|
919
|
+
dependencyType: "stateVariable",
|
|
920
|
+
variableName: "propIndex",
|
|
921
|
+
},
|
|
922
|
+
};
|
|
923
|
+
|
|
924
|
+
if (stateValues.effectivePropNameBySource !== null) {
|
|
925
|
+
for (let [
|
|
926
|
+
ind,
|
|
927
|
+
propName,
|
|
928
|
+
] of stateValues.effectivePropNameBySource.entries()) {
|
|
929
|
+
if (propName) {
|
|
930
|
+
// if we have a propName, then we just need the array size state variable,
|
|
931
|
+
// as we need to update only if a component changes
|
|
932
|
+
// or the size of the corresponding array changes.
|
|
933
|
+
// (The actual values of the prop state variables will
|
|
934
|
+
// be updated directly through dependencies)
|
|
935
|
+
|
|
936
|
+
let source = stateValues.replacementSourceIdentities[ind];
|
|
937
|
+
|
|
938
|
+
dependencies["sourceArraySize" + ind] = {
|
|
939
|
+
dependencyType: "stateVariableArraySize",
|
|
940
|
+
componentName: source.componentName,
|
|
941
|
+
variableName: propName,
|
|
942
|
+
variablesOptional: true,
|
|
943
|
+
caseInsensitiveVariableMatch: true,
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
dependencies["sourceComponentType" + ind] = {
|
|
947
|
+
dependencyType: "stateVariableComponentType",
|
|
948
|
+
componentName: source.componentName,
|
|
949
|
+
variableName: propName,
|
|
950
|
+
variablesOptional: true,
|
|
951
|
+
caseInsensitiveVariableMatch: true,
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
if (
|
|
958
|
+
stateValues.targetComponent !== null &&
|
|
959
|
+
componentInfoObjects.isCompositeComponent({
|
|
960
|
+
componentType: stateValues.targetComponent.componentType,
|
|
961
|
+
includeNonStandard: false,
|
|
962
|
+
}) &&
|
|
963
|
+
!(stateValues.propName && stateValues.obtainPropFromComposite)
|
|
964
|
+
) {
|
|
965
|
+
// Include identities of all replacements (and inactive target variable)
|
|
966
|
+
// without filtering by componentIndex,
|
|
967
|
+
// as components other than the one at that index could change
|
|
968
|
+
// the identity of the component at the relevant index
|
|
969
|
+
|
|
970
|
+
dependencies.allReplacementIdentities = {
|
|
971
|
+
dependencyType: "replacement",
|
|
972
|
+
compositeName: stateValues.targetComponent.componentName,
|
|
973
|
+
recursive: true,
|
|
974
|
+
variableNames: ["isInactiveCompositeReplacement"],
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if (stateValues.removeEmptyArrayEntries) {
|
|
979
|
+
// if we are to remove empty array entries,
|
|
980
|
+
// then we have to recalculate whenever replacement sources change
|
|
981
|
+
dependencies.replacementSources = {
|
|
982
|
+
dependencyType: "stateVariable",
|
|
983
|
+
variableName: "replacementSources",
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
return dependencies;
|
|
988
|
+
},
|
|
989
|
+
// the whole point of this state variable is to return updateReplacements
|
|
990
|
+
// on mark stale
|
|
991
|
+
markStale() {
|
|
992
|
+
return { updateReplacements: true };
|
|
993
|
+
},
|
|
994
|
+
definition: () => ({
|
|
995
|
+
setValue: { needsReplacementsUpdatedWhenStale: true },
|
|
996
|
+
}),
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
stateVariableDefinitions.effectiveAssignNames = {
|
|
1000
|
+
returnDependencies: () => ({
|
|
1001
|
+
assignNames: {
|
|
1002
|
+
dependencyType: "doenetAttribute",
|
|
1003
|
+
attributeName: "assignNames",
|
|
1004
|
+
},
|
|
1005
|
+
addLevelToAssignNames: {
|
|
1006
|
+
dependencyType: "stateVariable",
|
|
1007
|
+
variableName: "addLevelToAssignNames",
|
|
1008
|
+
},
|
|
1009
|
+
}),
|
|
1010
|
+
definition({ dependencyValues }) {
|
|
1011
|
+
let effectiveAssignNames = dependencyValues.assignNames;
|
|
1012
|
+
|
|
1013
|
+
if (effectiveAssignNames && dependencyValues.addLevelToAssignNames) {
|
|
1014
|
+
effectiveAssignNames = [effectiveAssignNames];
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
return { setValue: { effectiveAssignNames } };
|
|
1018
|
+
},
|
|
1019
|
+
};
|
|
1020
|
+
|
|
1021
|
+
return stateVariableDefinitions;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
static async createSerializedReplacements({
|
|
1025
|
+
component,
|
|
1026
|
+
components,
|
|
1027
|
+
workspace,
|
|
1028
|
+
componentInfoObjects,
|
|
1029
|
+
flags,
|
|
1030
|
+
resolveItem,
|
|
1031
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
1032
|
+
}) {
|
|
1033
|
+
// console.log(`create serialized replacements of ${component.componentName}`)
|
|
1034
|
+
|
|
1035
|
+
// console.log(await component.stateValues.targetComponent);
|
|
1036
|
+
// console.log(await component.stateValues.effectivePropNameBySource);
|
|
1037
|
+
// console.log(await component.stateValues.replacementSources)
|
|
1038
|
+
|
|
1039
|
+
// evaluate numComponentsSpecified so get error if specify numComponents without createComponentOfType
|
|
1040
|
+
await component.stateValues.numComponentsSpecified;
|
|
1041
|
+
|
|
1042
|
+
workspace.numReplacementsBySource = [];
|
|
1043
|
+
workspace.numNonStringReplacementsBySource = [];
|
|
1044
|
+
workspace.propVariablesCopiedBySource = [];
|
|
1045
|
+
workspace.sourceNames = [];
|
|
1046
|
+
workspace.uniqueIdentifiersUsedBySource = {};
|
|
1047
|
+
|
|
1048
|
+
let newNamespace = component.attributes.newNamespace?.primitive;
|
|
1049
|
+
|
|
1050
|
+
let compositeAttributesObj = this.createAttributesObject();
|
|
1051
|
+
|
|
1052
|
+
let assignNames = await component.stateValues.effectiveAssignNames;
|
|
1053
|
+
|
|
1054
|
+
let serializedComponentsForCid = await component.stateValues
|
|
1055
|
+
.serializedComponentsForCid;
|
|
1056
|
+
|
|
1057
|
+
if (serializedComponentsForCid) {
|
|
1058
|
+
let replacements = deepClone([serializedComponentsForCid[0]]);
|
|
1059
|
+
|
|
1060
|
+
let additionalChildren = deepClone(serializedComponentsForCid.slice(1));
|
|
1061
|
+
|
|
1062
|
+
if (replacements[0].children) {
|
|
1063
|
+
let namespace;
|
|
1064
|
+
if (replacements[0].componentName) {
|
|
1065
|
+
namespace = replacements[0].componentName + "/";
|
|
1066
|
+
} else {
|
|
1067
|
+
namespace = replacements[0].originalName + "/";
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
if (component.doenetAttributes.keptNewNamespaceOfLastChild) {
|
|
1071
|
+
namespace = namespace.slice(0, namespace.length - 1);
|
|
1072
|
+
let lastSlash = namespace.lastIndexOf("/");
|
|
1073
|
+
namespace = namespace.slice(0, lastSlash + 1);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
serializeFunctions.restrictTNamesToNamespace({
|
|
1077
|
+
components: replacements[0].children,
|
|
1078
|
+
namespace,
|
|
1079
|
+
invalidateReferencesToBaseNamespace:
|
|
1080
|
+
component.doenetAttributes.keptNewNamespaceOfLastChild,
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
if (replacements[0].componentType === "externalContent") {
|
|
1085
|
+
// replacements[0] is externalContent
|
|
1086
|
+
// add any specified attributes to its children
|
|
1087
|
+
for (let repl of replacements[0].children) {
|
|
1088
|
+
if (typeof repl !== "object") {
|
|
1089
|
+
continue;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// add attributes
|
|
1093
|
+
if (!repl.attributes) {
|
|
1094
|
+
repl.attributes = {};
|
|
1095
|
+
}
|
|
1096
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
1097
|
+
attributes: component.attributes,
|
|
1098
|
+
componentType: repl.componentType,
|
|
1099
|
+
componentInfoObjects,
|
|
1100
|
+
compositeAttributesObj,
|
|
1101
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
1102
|
+
flags,
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
for (let attrName in attributesFromComposite) {
|
|
1106
|
+
let attribute = attributesFromComposite[attrName];
|
|
1107
|
+
if (attribute.component) {
|
|
1108
|
+
serializeFunctions.setTNamesToAbsolute([attribute.component]);
|
|
1109
|
+
} else if (attribute.childrenForComponent) {
|
|
1110
|
+
serializeFunctions.setTNamesToAbsolute(
|
|
1111
|
+
attribute.childrenForComponent,
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
Object.assign(repl.attributes, attributesFromComposite);
|
|
1117
|
+
}
|
|
1118
|
+
} else {
|
|
1119
|
+
// if replacements[0] is not an externalContent, add attributes to replacements[0] itself
|
|
1120
|
+
if (!replacements[0].attributes) {
|
|
1121
|
+
replacements[0].attributes = {};
|
|
1122
|
+
}
|
|
1123
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
1124
|
+
attributes: component.attributes,
|
|
1125
|
+
componentType: replacements[0].componentType,
|
|
1126
|
+
componentInfoObjects,
|
|
1127
|
+
compositeAttributesObj,
|
|
1128
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
1129
|
+
flags,
|
|
1130
|
+
});
|
|
1131
|
+
|
|
1132
|
+
for (let attrName in attributesFromComposite) {
|
|
1133
|
+
let attribute = attributesFromComposite[attrName];
|
|
1134
|
+
if (attribute.component) {
|
|
1135
|
+
serializeFunctions.setTNamesToAbsolute([attribute.component]);
|
|
1136
|
+
} else if (attribute.childrenForComponent) {
|
|
1137
|
+
serializeFunctions.setTNamesToAbsolute(
|
|
1138
|
+
attribute.childrenForComponent,
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
Object.assign(replacements[0].attributes, attributesFromComposite);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
let processResult = serializeFunctions.processAssignNames({
|
|
1147
|
+
assignNames,
|
|
1148
|
+
assignNewNamespaces:
|
|
1149
|
+
component.attributes.assignNewNamespaces?.primitive,
|
|
1150
|
+
serializedComponents: replacements,
|
|
1151
|
+
parentName: component.componentName,
|
|
1152
|
+
parentCreatesNewNamespace: newNamespace,
|
|
1153
|
+
componentInfoObjects,
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1156
|
+
replacements = processResult.serializedComponents;
|
|
1157
|
+
|
|
1158
|
+
// if have copyFromURI, then add additional children from the composite itself
|
|
1159
|
+
if (
|
|
1160
|
+
component.doenetAttributes.fromCopyFromURI &&
|
|
1161
|
+
additionalChildren.length > 0
|
|
1162
|
+
) {
|
|
1163
|
+
this.addChildrenFromComposite({
|
|
1164
|
+
replacements,
|
|
1165
|
+
children: additionalChildren,
|
|
1166
|
+
assignNewNamespaces:
|
|
1167
|
+
component.attributes.assignNewNamespaces?.primitive,
|
|
1168
|
+
componentInfoObjects,
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
1173
|
+
component,
|
|
1174
|
+
replacements,
|
|
1175
|
+
assignNames,
|
|
1176
|
+
workspace,
|
|
1177
|
+
componentInfoObjects,
|
|
1178
|
+
compositeAttributesObj,
|
|
1179
|
+
flags,
|
|
1180
|
+
});
|
|
1181
|
+
|
|
1182
|
+
return { replacements: verificationResult.replacements };
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
// if have a sourceIndex, it means we are copying the indexAlias from a source
|
|
1186
|
+
// so we just return a number that is the index
|
|
1187
|
+
let sourceIndex = await component.stateValues.sourceIndex;
|
|
1188
|
+
if (sourceIndex !== null) {
|
|
1189
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
1190
|
+
attributes: component.attributes,
|
|
1191
|
+
componentType: "number",
|
|
1192
|
+
componentInfoObjects,
|
|
1193
|
+
compositeAttributesObj,
|
|
1194
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
1195
|
+
flags,
|
|
1196
|
+
});
|
|
1197
|
+
|
|
1198
|
+
let replacements = [
|
|
1199
|
+
{
|
|
1200
|
+
componentType: "number",
|
|
1201
|
+
attributes: attributesFromComposite,
|
|
1202
|
+
state: { value: sourceIndex, fixed: true },
|
|
1203
|
+
},
|
|
1204
|
+
];
|
|
1205
|
+
|
|
1206
|
+
let processResult = serializeFunctions.processAssignNames({
|
|
1207
|
+
assignNames,
|
|
1208
|
+
serializedComponents: replacements,
|
|
1209
|
+
parentName: component.componentName,
|
|
1210
|
+
parentCreatesNewNamespace: newNamespace,
|
|
1211
|
+
componentInfoObjects,
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
1215
|
+
component,
|
|
1216
|
+
replacements: processResult.serializedComponents,
|
|
1217
|
+
assignNames,
|
|
1218
|
+
workspace,
|
|
1219
|
+
componentInfoObjects,
|
|
1220
|
+
compositeAttributesObj,
|
|
1221
|
+
flags,
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
return { replacements: verificationResult.replacements };
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
let replacementSourceIdentities = await component.stateValues
|
|
1228
|
+
.replacementSourceIdentities;
|
|
1229
|
+
if (
|
|
1230
|
+
!(await component.stateValues.targetComponent) ||
|
|
1231
|
+
!replacementSourceIdentities
|
|
1232
|
+
) {
|
|
1233
|
+
// no valid target, so no replacements
|
|
1234
|
+
let replacements = [];
|
|
1235
|
+
|
|
1236
|
+
if (component.doenetAttributes.fromCopyTarget) {
|
|
1237
|
+
// even though don't have valid target,
|
|
1238
|
+
// if have copyTarget, then include children added directly to component
|
|
1239
|
+
|
|
1240
|
+
let componentType =
|
|
1241
|
+
componentInfoObjects.componentTypeLowerCaseMapping[
|
|
1242
|
+
component.attributes.createComponentOfType.primitive.toLowerCase()
|
|
1243
|
+
];
|
|
1244
|
+
|
|
1245
|
+
let componentClass =
|
|
1246
|
+
componentInfoObjects.allComponentClasses[componentType];
|
|
1247
|
+
|
|
1248
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
1249
|
+
attributes: component.attributes,
|
|
1250
|
+
componentType,
|
|
1251
|
+
componentInfoObjects,
|
|
1252
|
+
compositeAttributesObj,
|
|
1253
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
1254
|
+
flags,
|
|
1255
|
+
});
|
|
1256
|
+
|
|
1257
|
+
workspace.uniqueIdentifiersUsedBySource[0] = [];
|
|
1258
|
+
let uniqueIdentifierBase = componentType + "|empty";
|
|
1259
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
1260
|
+
uniqueIdentifierBase,
|
|
1261
|
+
workspace.uniqueIdentifiersUsedBySource[0],
|
|
1262
|
+
);
|
|
1263
|
+
|
|
1264
|
+
let children = deepClone(component.serializedChildren);
|
|
1265
|
+
if (!componentClass.includeBlankStringChildren) {
|
|
1266
|
+
children = children.filter(
|
|
1267
|
+
(x) => typeof x !== "string" || x.trim() !== "",
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
let attributes = attributesFromComposite;
|
|
1272
|
+
if (component.attributes.assignNewNamespaces?.primitive) {
|
|
1273
|
+
attributes.newNamespace = { primitive: true };
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
replacements = [
|
|
1277
|
+
{
|
|
1278
|
+
componentType,
|
|
1279
|
+
attributes,
|
|
1280
|
+
children,
|
|
1281
|
+
uniqueIdentifier,
|
|
1282
|
+
},
|
|
1283
|
+
];
|
|
1284
|
+
|
|
1285
|
+
let processResult = serializeFunctions.processAssignNames({
|
|
1286
|
+
assignNames,
|
|
1287
|
+
serializedComponents: replacements,
|
|
1288
|
+
parentName: component.componentName,
|
|
1289
|
+
componentInfoObjects,
|
|
1290
|
+
originalNamesAreConsistent: true,
|
|
1291
|
+
});
|
|
1292
|
+
|
|
1293
|
+
replacements = processResult.serializedComponents;
|
|
1294
|
+
|
|
1295
|
+
workspace.numReplacementsBySource.push(replacements.length);
|
|
1296
|
+
workspace.numNonStringReplacementsBySource.push(
|
|
1297
|
+
replacements.filter((x) => typeof x !== "string").length,
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
1302
|
+
component,
|
|
1303
|
+
replacements,
|
|
1304
|
+
assignNames,
|
|
1305
|
+
workspace,
|
|
1306
|
+
componentInfoObjects,
|
|
1307
|
+
compositeAttributesObj,
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
return { replacements: verificationResult.replacements };
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// resolve determine dependencies of replacementSources
|
|
1314
|
+
// and resolve recalculateDownstreamComponents of its target dependencies
|
|
1315
|
+
// so any array entry prop is created
|
|
1316
|
+
let resolveResult = await resolveItem({
|
|
1317
|
+
componentName: component.componentName,
|
|
1318
|
+
type: "determineDependencies",
|
|
1319
|
+
stateVariable: "replacementSources",
|
|
1320
|
+
dependency: "__determine_dependencies",
|
|
1321
|
+
expandComposites: false,
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
if (!resolveResult.success) {
|
|
1325
|
+
throw Error(
|
|
1326
|
+
`Couldn't resolve determineDependencies of replacementSources of ${component.componentName}`,
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
let effectivePropNameBySource = await component.stateValues
|
|
1331
|
+
.effectivePropNameBySource;
|
|
1332
|
+
for (let ind in replacementSourceIdentities) {
|
|
1333
|
+
let thisPropName = effectivePropNameBySource[ind];
|
|
1334
|
+
|
|
1335
|
+
if (thisPropName) {
|
|
1336
|
+
resolveResult = await resolveItem({
|
|
1337
|
+
componentName: component.componentName,
|
|
1338
|
+
type: "recalculateDownstreamComponents",
|
|
1339
|
+
stateVariable: "replacementSources",
|
|
1340
|
+
dependency: "target" + ind,
|
|
1341
|
+
expandComposites: false,
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
if (!resolveResult.success) {
|
|
1345
|
+
throw Error(
|
|
1346
|
+
`Couldn't resolve recalculateDownstreamComponents for target${ind} of replacementSources of ${component.componentName}`,
|
|
1347
|
+
);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
let replacements = [];
|
|
1353
|
+
|
|
1354
|
+
let numReplacementsBySource = [];
|
|
1355
|
+
let numNonStringReplacementsBySource = [];
|
|
1356
|
+
let numReplacementsSoFar = 0;
|
|
1357
|
+
let numNonStringReplacementsSoFar = 0;
|
|
1358
|
+
|
|
1359
|
+
for (let sourceNum in replacementSourceIdentities) {
|
|
1360
|
+
let uniqueIdentifiersUsed = (workspace.uniqueIdentifiersUsedBySource[
|
|
1361
|
+
sourceNum
|
|
1362
|
+
] = []);
|
|
1363
|
+
|
|
1364
|
+
let numComponentsForSource;
|
|
1365
|
+
|
|
1366
|
+
if (component.attributes.createComponentOfType?.primitive) {
|
|
1367
|
+
let numComponentsTotal = await component.stateValues
|
|
1368
|
+
.numComponentsSpecified;
|
|
1369
|
+
let numSources = replacementSourceIdentities.length;
|
|
1370
|
+
|
|
1371
|
+
// arbitrarily divide these components among the sources
|
|
1372
|
+
numComponentsForSource = Math.floor(numComponentsTotal / numSources);
|
|
1373
|
+
let nExtras = numComponentsTotal % numSources;
|
|
1374
|
+
if (sourceNum < nExtras) {
|
|
1375
|
+
numComponentsForSource++;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
let results = await this.createReplacementForSource({
|
|
1380
|
+
component,
|
|
1381
|
+
sourceNum,
|
|
1382
|
+
components,
|
|
1383
|
+
numReplacementsSoFar,
|
|
1384
|
+
numNonStringReplacementsSoFar,
|
|
1385
|
+
uniqueIdentifiersUsed,
|
|
1386
|
+
compositeAttributesObj,
|
|
1387
|
+
componentInfoObjects,
|
|
1388
|
+
numComponentsForSource,
|
|
1389
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
1390
|
+
flags,
|
|
1391
|
+
fromCopyTarget:
|
|
1392
|
+
Number(sourceNum) === 0 && component.doenetAttributes.fromCopyTarget,
|
|
1393
|
+
});
|
|
1394
|
+
|
|
1395
|
+
workspace.propVariablesCopiedBySource[sourceNum] =
|
|
1396
|
+
results.propVariablesCopiedByReplacement;
|
|
1397
|
+
|
|
1398
|
+
let sourceReplacements = results.serializedReplacements;
|
|
1399
|
+
numReplacementsBySource[sourceNum] = sourceReplacements.length;
|
|
1400
|
+
numNonStringReplacementsBySource[sourceNum] = sourceReplacements.filter(
|
|
1401
|
+
(x) => typeof x !== "string",
|
|
1402
|
+
).length;
|
|
1403
|
+
numReplacementsSoFar += numReplacementsBySource[sourceNum];
|
|
1404
|
+
numNonStringReplacementsSoFar +=
|
|
1405
|
+
numNonStringReplacementsBySource[sourceNum];
|
|
1406
|
+
replacements.push(...sourceReplacements);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
workspace.numReplacementsBySource = numReplacementsBySource;
|
|
1410
|
+
workspace.numNonStringReplacementsBySource =
|
|
1411
|
+
numNonStringReplacementsBySource;
|
|
1412
|
+
workspace.sourceNames = replacementSourceIdentities.map(
|
|
1413
|
+
(x) => x.componentName,
|
|
1414
|
+
);
|
|
1415
|
+
|
|
1416
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
1417
|
+
component,
|
|
1418
|
+
replacements,
|
|
1419
|
+
assignNames,
|
|
1420
|
+
workspace,
|
|
1421
|
+
componentInfoObjects,
|
|
1422
|
+
compositeAttributesObj,
|
|
1423
|
+
flags,
|
|
1424
|
+
});
|
|
1425
|
+
|
|
1426
|
+
// console.log(`serialized replacements for ${component.componentName}`)
|
|
1427
|
+
// console.log(JSON.parse(JSON.stringify(verificationResult.replacements)))
|
|
1428
|
+
|
|
1429
|
+
return { replacements: verificationResult.replacements };
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
static async createReplacementForSource({
|
|
1433
|
+
component,
|
|
1434
|
+
sourceNum,
|
|
1435
|
+
components,
|
|
1436
|
+
numReplacementsSoFar,
|
|
1437
|
+
numNonStringReplacementsSoFar,
|
|
1438
|
+
uniqueIdentifiersUsed,
|
|
1439
|
+
compositeAttributesObj,
|
|
1440
|
+
componentInfoObjects,
|
|
1441
|
+
numComponentsForSource,
|
|
1442
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
1443
|
+
flags,
|
|
1444
|
+
fromCopyTarget,
|
|
1445
|
+
}) {
|
|
1446
|
+
// console.log(`create replacement for sourceNum ${sourceNum}`)
|
|
1447
|
+
// console.log(`propName: ${component.stateValues.effectivePropNameBySource[sourceNum]}`)
|
|
1448
|
+
|
|
1449
|
+
let replacementSource = (
|
|
1450
|
+
await component.stateValues.replacementSourceIdentities
|
|
1451
|
+
)[sourceNum];
|
|
1452
|
+
if (typeof replacementSource !== "object") {
|
|
1453
|
+
return { serializedReplacements: [replacementSource] };
|
|
1454
|
+
}
|
|
1455
|
+
let replacementSourceComponent =
|
|
1456
|
+
components[replacementSource.componentName];
|
|
1457
|
+
|
|
1458
|
+
// if not linking or removing empty array entries,
|
|
1459
|
+
// then replacementSources is resolved,
|
|
1460
|
+
// which we need for state variable value
|
|
1461
|
+
let link = await component.stateValues.link;
|
|
1462
|
+
if (!link || (await component.stateValues.removeEmptyArrayEntries)) {
|
|
1463
|
+
replacementSource = (await component.stateValues.replacementSources)[
|
|
1464
|
+
sourceNum
|
|
1465
|
+
];
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
let newNamespace = component.attributes.newNamespace?.primitive;
|
|
1469
|
+
|
|
1470
|
+
let assignNames = await component.stateValues.effectiveAssignNames;
|
|
1471
|
+
|
|
1472
|
+
// if creating copy from a prop
|
|
1473
|
+
// manually create the serialized component
|
|
1474
|
+
let propName = (await component.stateValues.effectivePropNameBySource)[
|
|
1475
|
+
sourceNum
|
|
1476
|
+
];
|
|
1477
|
+
if (propName) {
|
|
1478
|
+
let results = await replacementFromProp({
|
|
1479
|
+
component,
|
|
1480
|
+
components,
|
|
1481
|
+
replacementSource,
|
|
1482
|
+
propName,
|
|
1483
|
+
numReplacementsSoFar,
|
|
1484
|
+
numNonStringReplacementsSoFar,
|
|
1485
|
+
uniqueIdentifiersUsed,
|
|
1486
|
+
compositeAttributesObj,
|
|
1487
|
+
componentInfoObjects,
|
|
1488
|
+
numComponentsForSource,
|
|
1489
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
1490
|
+
flags,
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
let processResult = serializeFunctions.processAssignNames({
|
|
1494
|
+
assignNames,
|
|
1495
|
+
serializedComponents: results.serializedReplacements,
|
|
1496
|
+
parentName: component.componentName,
|
|
1497
|
+
parentCreatesNewNamespace: newNamespace,
|
|
1498
|
+
indOffset: numNonStringReplacementsSoFar,
|
|
1499
|
+
componentInfoObjects,
|
|
1500
|
+
});
|
|
1501
|
+
|
|
1502
|
+
return {
|
|
1503
|
+
serializedReplacements: processResult.serializedComponents,
|
|
1504
|
+
propVariablesCopiedByReplacement:
|
|
1505
|
+
results.propVariablesCopiedByReplacement,
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
// if creating copy directly from the target component,
|
|
1510
|
+
// create a serialized copy of the entire component
|
|
1511
|
+
|
|
1512
|
+
let sourceAttributesToIgnore = await component.stateValues
|
|
1513
|
+
.sourceAttributesToIgnore;
|
|
1514
|
+
|
|
1515
|
+
let serializedReplacements = [
|
|
1516
|
+
await replacementSourceComponent.serialize({
|
|
1517
|
+
copyAll: !link,
|
|
1518
|
+
copyVariants: !link,
|
|
1519
|
+
sourceAttributesToIgnore,
|
|
1520
|
+
}),
|
|
1521
|
+
];
|
|
1522
|
+
|
|
1523
|
+
// when copying with link=false, ignore fixed if from essential state
|
|
1524
|
+
// so that, for example, a copy from a sequence with link=false is not fixed
|
|
1525
|
+
if (!link && serializedReplacements[0].state?.fixed !== undefined) {
|
|
1526
|
+
delete serializedReplacements[0].state.fixed;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
// console.log(`serializedReplacements for ${component.componentName}`);
|
|
1530
|
+
// console.log(JSON.parse(JSON.stringify(serializedReplacements)));
|
|
1531
|
+
|
|
1532
|
+
serializedReplacements = postProcessCopy({
|
|
1533
|
+
serializedComponents: serializedReplacements,
|
|
1534
|
+
componentName: component.componentName,
|
|
1535
|
+
uniqueIdentifiersUsed,
|
|
1536
|
+
addShadowDependencies: link,
|
|
1537
|
+
unlinkExternalCopies: !link,
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
if (serializedReplacements.length > 0) {
|
|
1541
|
+
delete serializedReplacements[0].doenetAttributes
|
|
1542
|
+
.haveNewNamespaceOnlyFromShadow;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
for (let repl of serializedReplacements) {
|
|
1546
|
+
if (typeof repl !== "object") {
|
|
1547
|
+
continue;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
// add attributes
|
|
1551
|
+
if (!repl.attributes) {
|
|
1552
|
+
repl.attributes = {};
|
|
1553
|
+
}
|
|
1554
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
1555
|
+
attributes: component.attributes,
|
|
1556
|
+
componentType: repl.componentType,
|
|
1557
|
+
componentInfoObjects,
|
|
1558
|
+
compositeAttributesObj,
|
|
1559
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
1560
|
+
flags,
|
|
1561
|
+
});
|
|
1562
|
+
Object.assign(repl.attributes, attributesFromComposite);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
if (
|
|
1566
|
+
serializedReplacements[0].attributes.newNamespace?.primitive &&
|
|
1567
|
+
!component.attributes.assignNewNamespaces?.primitive
|
|
1568
|
+
) {
|
|
1569
|
+
serializedReplacements[0].doenetAttributes.haveNewNamespaceOnlyFromShadow = true;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
let processResult = serializeFunctions.processAssignNames({
|
|
1573
|
+
assignNames,
|
|
1574
|
+
assignNewNamespaces: component.attributes.assignNewNamespaces?.primitive,
|
|
1575
|
+
serializedComponents: serializedReplacements,
|
|
1576
|
+
parentName: component.componentName,
|
|
1577
|
+
parentCreatesNewNamespace: newNamespace,
|
|
1578
|
+
indOffset: numNonStringReplacementsSoFar,
|
|
1579
|
+
componentInfoObjects,
|
|
1580
|
+
originalNamesAreConsistent: newNamespace && !assignNames,
|
|
1581
|
+
});
|
|
1582
|
+
|
|
1583
|
+
serializedReplacements = processResult.serializedComponents;
|
|
1584
|
+
|
|
1585
|
+
// if have copy target, then add additional children from the composite itself
|
|
1586
|
+
if (
|
|
1587
|
+
fromCopyTarget &&
|
|
1588
|
+
serializedReplacements.length === 1 &&
|
|
1589
|
+
component.serializedChildren.length > 0
|
|
1590
|
+
) {
|
|
1591
|
+
this.addChildrenFromComposite({
|
|
1592
|
+
replacements: serializedReplacements,
|
|
1593
|
+
children: component.serializedChildren,
|
|
1594
|
+
assignNewNamespaces:
|
|
1595
|
+
component.attributes.assignNewNamespaces?.primitive,
|
|
1596
|
+
componentInfoObjects,
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
// console.log(`ending serializedReplacements for ${component.componentName}`);
|
|
1601
|
+
// console.log(JSON.parse(JSON.stringify(serializedReplacements)));
|
|
1602
|
+
|
|
1603
|
+
return { serializedReplacements };
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
static addChildrenFromComposite({
|
|
1607
|
+
replacements,
|
|
1608
|
+
children,
|
|
1609
|
+
assignNewNamespaces,
|
|
1610
|
+
componentInfoObjects,
|
|
1611
|
+
}) {
|
|
1612
|
+
let repl = replacements[0];
|
|
1613
|
+
if (!repl.children) {
|
|
1614
|
+
repl.children = [];
|
|
1615
|
+
}
|
|
1616
|
+
let newChildren = deepClone(children);
|
|
1617
|
+
let componentClass =
|
|
1618
|
+
componentInfoObjects.allComponentClasses[repl.componentType];
|
|
1619
|
+
|
|
1620
|
+
if (!componentClass.includeBlankStringChildren) {
|
|
1621
|
+
newChildren = newChildren.filter(
|
|
1622
|
+
(x) => typeof x !== "string" || x.trim() !== "",
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
if (
|
|
1627
|
+
replacements[0].attributes.newNamespace?.primitive &&
|
|
1628
|
+
assignNewNamespaces
|
|
1629
|
+
) {
|
|
1630
|
+
// if the new components were added with a new namespace
|
|
1631
|
+
// and their parent had a new namespace
|
|
1632
|
+
// make the auto numbered component names include the names
|
|
1633
|
+
// from the original children so that don't have a name collision
|
|
1634
|
+
// from the autonumbering
|
|
1635
|
+
let componentCounts =
|
|
1636
|
+
serializeFunctions.countRegularComponentTypesInNamespace(repl.children);
|
|
1637
|
+
|
|
1638
|
+
serializeFunctions.renameAutonameBasedOnNewCounts(
|
|
1639
|
+
newChildren,
|
|
1640
|
+
componentCounts,
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
let processResult = serializeFunctions.processAssignNames({
|
|
1645
|
+
serializedComponents: newChildren,
|
|
1646
|
+
parentName: replacements[0].componentName,
|
|
1647
|
+
parentCreatesNewNamespace: assignNewNamespaces,
|
|
1648
|
+
componentInfoObjects,
|
|
1649
|
+
originalNamesAreConsistent: true,
|
|
1650
|
+
});
|
|
1651
|
+
|
|
1652
|
+
if (
|
|
1653
|
+
replacements[0].attributes.newNamespace?.primitive &&
|
|
1654
|
+
!assignNewNamespaces
|
|
1655
|
+
) {
|
|
1656
|
+
// the new components were added without a new namespace
|
|
1657
|
+
// even though their parent had a new namespace
|
|
1658
|
+
// The parent has already been marked as having a new namespace only because it is shadowing.
|
|
1659
|
+
// Mark them to ignore their parent's new namespace.
|
|
1660
|
+
// Then if the parent is copied directly,
|
|
1661
|
+
// the children won't be given a new namespace
|
|
1662
|
+
for (let comp of processResult.serializedComponents) {
|
|
1663
|
+
if (typeof comp === "object") {
|
|
1664
|
+
comp.doenetAttributes.ignoreParentNewNamespace = true;
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
repl.children.push(...processResult.serializedComponents);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
static async calculateReplacementChanges({
|
|
1673
|
+
component,
|
|
1674
|
+
componentChanges,
|
|
1675
|
+
components,
|
|
1676
|
+
workspace,
|
|
1677
|
+
componentInfoObjects,
|
|
1678
|
+
flags,
|
|
1679
|
+
resolveItem,
|
|
1680
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
1681
|
+
}) {
|
|
1682
|
+
// console.log("Calculating replacement changes for " + component.componentName);
|
|
1683
|
+
|
|
1684
|
+
// if copying a cid, no changes
|
|
1685
|
+
if (await component.stateValues.serializedComponentsForCid) {
|
|
1686
|
+
return [];
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
// for indexAlias from a source, the replacements never change
|
|
1690
|
+
if ((await component.stateValues.sourceIndex) !== null) {
|
|
1691
|
+
return [];
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
let compositeAttributesObj = this.createAttributesObject();
|
|
1695
|
+
|
|
1696
|
+
let assignNames = await component.stateValues.effectiveAssignNames;
|
|
1697
|
+
|
|
1698
|
+
let replacementSourceIdentities = await component.stateValues
|
|
1699
|
+
.replacementSourceIdentities;
|
|
1700
|
+
if (
|
|
1701
|
+
!(await component.stateValues.targetComponent) ||
|
|
1702
|
+
!replacementSourceIdentities
|
|
1703
|
+
) {
|
|
1704
|
+
if (await component.stateValues.targetSources) {
|
|
1705
|
+
// if have targetSources, then we're in a template instance
|
|
1706
|
+
// that will be withheld
|
|
1707
|
+
// Don't change replacements so that maintain replacement
|
|
1708
|
+
// if the template instance is later no longer withheld
|
|
1709
|
+
return [];
|
|
1710
|
+
} else {
|
|
1711
|
+
let replacementChanges = [];
|
|
1712
|
+
|
|
1713
|
+
if (component.replacements.length > 0) {
|
|
1714
|
+
let replacementInstruction = {
|
|
1715
|
+
changeType: "delete",
|
|
1716
|
+
changeTopLevelReplacements: true,
|
|
1717
|
+
firstReplacementInd: 0,
|
|
1718
|
+
numberReplacementsToDelete: component.replacements.length,
|
|
1719
|
+
};
|
|
1720
|
+
replacementChanges.push(replacementInstruction);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
let previousZeroSourceNames = workspace.sourceNames.length === 0;
|
|
1724
|
+
|
|
1725
|
+
workspace.sourceNames = [];
|
|
1726
|
+
workspace.numReplacementsBySource = [];
|
|
1727
|
+
workspace.numNonStringReplacementsBySource = [];
|
|
1728
|
+
workspace.propVariablesCopiedBySource = [];
|
|
1729
|
+
|
|
1730
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
1731
|
+
component,
|
|
1732
|
+
replacementChanges,
|
|
1733
|
+
assignNames,
|
|
1734
|
+
workspace,
|
|
1735
|
+
componentInfoObjects,
|
|
1736
|
+
compositeAttributesObj,
|
|
1737
|
+
flags,
|
|
1738
|
+
});
|
|
1739
|
+
|
|
1740
|
+
// Note: this has to run after verify,
|
|
1741
|
+
// as verify has side effects of setting workspace variables,
|
|
1742
|
+
// such as numReplacementsBySource
|
|
1743
|
+
if (previousZeroSourceNames) {
|
|
1744
|
+
// didn't have sources before and still don't have sources.
|
|
1745
|
+
// we're just getting filler components being recreated.
|
|
1746
|
+
// Don't actually make those changes
|
|
1747
|
+
return [];
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
return verificationResult.replacementChanges;
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
if (await component.stateValues.targetInactive) {
|
|
1755
|
+
let replacementChanges = [];
|
|
1756
|
+
|
|
1757
|
+
let nReplacements = component.replacements.length;
|
|
1758
|
+
if (nReplacements > 0) {
|
|
1759
|
+
if (component.replacementsToWithhold !== nReplacements) {
|
|
1760
|
+
let replacementInstruction = {
|
|
1761
|
+
changeType: "changeReplacementsToWithhold",
|
|
1762
|
+
replacementsToWithhold: nReplacements,
|
|
1763
|
+
};
|
|
1764
|
+
replacementChanges.push(replacementInstruction);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
1768
|
+
component,
|
|
1769
|
+
replacementChanges,
|
|
1770
|
+
assignNames,
|
|
1771
|
+
workspace,
|
|
1772
|
+
componentInfoObjects,
|
|
1773
|
+
compositeAttributesObj,
|
|
1774
|
+
flags,
|
|
1775
|
+
});
|
|
1776
|
+
|
|
1777
|
+
replacementChanges = verificationResult.replacementChanges;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
return replacementChanges;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// resolve determine dependencies of replacementSources
|
|
1784
|
+
// and resolve recalculateDownstreamComponents of its target dependencies
|
|
1785
|
+
// so any array entry prop is created
|
|
1786
|
+
let resolveResult = await resolveItem({
|
|
1787
|
+
componentName: component.componentName,
|
|
1788
|
+
type: "determineDependencies",
|
|
1789
|
+
stateVariable: "replacementSources",
|
|
1790
|
+
dependency: "__determine_dependencies",
|
|
1791
|
+
expandComposites: false,
|
|
1792
|
+
});
|
|
1793
|
+
|
|
1794
|
+
if (!resolveResult.success) {
|
|
1795
|
+
throw Error(
|
|
1796
|
+
`Couldn't resolve determineDependencies of replacementSources of ${component.componentName}`,
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
let effectivePropNameBySource = await component.stateValues
|
|
1801
|
+
.effectivePropNameBySource;
|
|
1802
|
+
|
|
1803
|
+
for (let ind in replacementSourceIdentities) {
|
|
1804
|
+
let thisPropName = effectivePropNameBySource[ind];
|
|
1805
|
+
|
|
1806
|
+
if (thisPropName) {
|
|
1807
|
+
resolveResult = await resolveItem({
|
|
1808
|
+
componentName: component.componentName,
|
|
1809
|
+
type: "recalculateDownstreamComponents",
|
|
1810
|
+
stateVariable: "replacementSources",
|
|
1811
|
+
dependency: "target" + ind,
|
|
1812
|
+
expandComposites: false,
|
|
1813
|
+
});
|
|
1814
|
+
|
|
1815
|
+
if (!resolveResult.success) {
|
|
1816
|
+
throw Error(
|
|
1817
|
+
`Couldn't resolve recalculateDownstreamComponents for target${ind} of replacementSources of ${component.componentName}`,
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
let replacementChanges = [];
|
|
1824
|
+
|
|
1825
|
+
if (component.replacementsToWithhold > 0) {
|
|
1826
|
+
let replacementInstruction = {
|
|
1827
|
+
changeType: "changeReplacementsToWithhold",
|
|
1828
|
+
replacementsToWithhold: 0,
|
|
1829
|
+
};
|
|
1830
|
+
replacementChanges.push(replacementInstruction);
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
let numReplacementsSoFar = 0;
|
|
1834
|
+
let numNonStringReplacementsSoFar = 0;
|
|
1835
|
+
|
|
1836
|
+
let numReplacementsBySource = [];
|
|
1837
|
+
let numNonStringReplacementsBySource = [];
|
|
1838
|
+
let propVariablesCopiedBySource = [];
|
|
1839
|
+
|
|
1840
|
+
let maxSourceLength = Math.max(
|
|
1841
|
+
replacementSourceIdentities.length,
|
|
1842
|
+
workspace.numReplacementsBySource.length,
|
|
1843
|
+
);
|
|
1844
|
+
|
|
1845
|
+
let recreateRemaining = false;
|
|
1846
|
+
|
|
1847
|
+
for (let sourceNum = 0; sourceNum < maxSourceLength; sourceNum++) {
|
|
1848
|
+
let numComponentsForSource;
|
|
1849
|
+
|
|
1850
|
+
if (component.attributes.createComponentOfType?.primitive) {
|
|
1851
|
+
let numComponentsTotal = await component.stateValues
|
|
1852
|
+
.numComponentsSpecified;
|
|
1853
|
+
let numSources = replacementSourceIdentities.length;
|
|
1854
|
+
|
|
1855
|
+
// arbitrarily divide these components among the sources
|
|
1856
|
+
numComponentsForSource = Math.floor(numComponentsTotal / numSources);
|
|
1857
|
+
let nExtras = numComponentsTotal % numSources;
|
|
1858
|
+
if (sourceNum < nExtras) {
|
|
1859
|
+
numComponentsForSource++;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
let replacementSource = replacementSourceIdentities[sourceNum];
|
|
1864
|
+
if (replacementSource === undefined) {
|
|
1865
|
+
if (workspace.numReplacementsBySource[sourceNum] > 0) {
|
|
1866
|
+
if (!recreateRemaining) {
|
|
1867
|
+
// since deleting replacement will shift the remaining replacements
|
|
1868
|
+
// and change resulting names,
|
|
1869
|
+
// delete all remaining and mark to be recreated
|
|
1870
|
+
|
|
1871
|
+
let numberReplacementsLeft = workspace.numReplacementsBySource
|
|
1872
|
+
.slice(sourceNum)
|
|
1873
|
+
.reduce((a, c) => a + c, 0);
|
|
1874
|
+
|
|
1875
|
+
if (numberReplacementsLeft > 0) {
|
|
1876
|
+
let replacementInstruction = {
|
|
1877
|
+
changeType: "delete",
|
|
1878
|
+
changeTopLevelReplacements: true,
|
|
1879
|
+
firstReplacementInd: numReplacementsSoFar,
|
|
1880
|
+
numberReplacementsToDelete: numberReplacementsLeft,
|
|
1881
|
+
};
|
|
1882
|
+
|
|
1883
|
+
replacementChanges.push(replacementInstruction);
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
recreateRemaining = true;
|
|
1887
|
+
|
|
1888
|
+
// since deleted remaining, change in workspace
|
|
1889
|
+
// so that don't attempt to delete again
|
|
1890
|
+
workspace.numReplacementsBySource
|
|
1891
|
+
.slice(sourceNum)
|
|
1892
|
+
.forEach((v, i) => (workspace.numReplacementsBySource[i] = 0));
|
|
1893
|
+
workspace.numNonStringReplacementsBySource
|
|
1894
|
+
.slice(sourceNum)
|
|
1895
|
+
.forEach(
|
|
1896
|
+
(v, i) => (workspace.numNonStringReplacementsBySource[i] = 0),
|
|
1897
|
+
);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
workspace.uniqueIdentifiersUsedBySource[sourceNum] = [];
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
numReplacementsBySource[sourceNum] = 0;
|
|
1904
|
+
numNonStringReplacementsBySource[sourceNum] = 0;
|
|
1905
|
+
propVariablesCopiedBySource.push([]);
|
|
1906
|
+
|
|
1907
|
+
continue;
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
let prevSourceName = workspace.sourceNames[sourceNum];
|
|
1911
|
+
|
|
1912
|
+
// check if replacementSource has changed
|
|
1913
|
+
let needToRecreate =
|
|
1914
|
+
prevSourceName === undefined ||
|
|
1915
|
+
replacementSource.componentName !== prevSourceName ||
|
|
1916
|
+
recreateRemaining;
|
|
1917
|
+
|
|
1918
|
+
if (!needToRecreate) {
|
|
1919
|
+
// make sure the current replacements still shadow the replacement source
|
|
1920
|
+
for (
|
|
1921
|
+
let ind = 0;
|
|
1922
|
+
ind < workspace.numReplacementsBySource[sourceNum];
|
|
1923
|
+
ind++
|
|
1924
|
+
) {
|
|
1925
|
+
let currentReplacement =
|
|
1926
|
+
component.replacements[numReplacementsSoFar + ind];
|
|
1927
|
+
if (!currentReplacement) {
|
|
1928
|
+
needToRecreate = true;
|
|
1929
|
+
break;
|
|
1930
|
+
} else if (
|
|
1931
|
+
!effectivePropNameBySource[sourceNum] &&
|
|
1932
|
+
currentReplacement.shadows &&
|
|
1933
|
+
currentReplacement.shadows.componentName !==
|
|
1934
|
+
replacementSourceIdentities[sourceNum].componentName
|
|
1935
|
+
) {
|
|
1936
|
+
needToRecreate = true;
|
|
1937
|
+
break;
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
if (needToRecreate) {
|
|
1943
|
+
let prevNumReplacements = 0;
|
|
1944
|
+
if (sourceNum in workspace.numReplacementsBySource) {
|
|
1945
|
+
prevNumReplacements = workspace.numReplacementsBySource[sourceNum];
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
let numReplacementsToDelete = prevNumReplacements;
|
|
1949
|
+
if (recreateRemaining) {
|
|
1950
|
+
// already deleted old replacements
|
|
1951
|
+
numReplacementsToDelete = 0;
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
let uniqueIdentifiersUsed = (workspace.uniqueIdentifiersUsedBySource[
|
|
1955
|
+
sourceNum
|
|
1956
|
+
] = []);
|
|
1957
|
+
let results = await this.recreateReplacements({
|
|
1958
|
+
component,
|
|
1959
|
+
sourceNum,
|
|
1960
|
+
numReplacementsSoFar,
|
|
1961
|
+
numNonStringReplacementsSoFar,
|
|
1962
|
+
numReplacementsToDelete,
|
|
1963
|
+
components,
|
|
1964
|
+
uniqueIdentifiersUsed,
|
|
1965
|
+
compositeAttributesObj,
|
|
1966
|
+
componentInfoObjects,
|
|
1967
|
+
numComponentsForSource,
|
|
1968
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
1969
|
+
flags,
|
|
1970
|
+
});
|
|
1971
|
+
|
|
1972
|
+
numReplacementsSoFar += results.numReplacements;
|
|
1973
|
+
numNonStringReplacementsSoFar += results.numNonStringReplacements;
|
|
1974
|
+
|
|
1975
|
+
numReplacementsBySource[sourceNum] = results.numReplacements;
|
|
1976
|
+
numNonStringReplacementsBySource[sourceNum] =
|
|
1977
|
+
results.numNonStringReplacements;
|
|
1978
|
+
|
|
1979
|
+
propVariablesCopiedBySource[sourceNum] =
|
|
1980
|
+
results.propVariablesCopiedByReplacement;
|
|
1981
|
+
|
|
1982
|
+
let replacementInstruction = results.replacementInstruction;
|
|
1983
|
+
|
|
1984
|
+
if (!recreateRemaining) {
|
|
1985
|
+
if (results.numReplacements !== prevNumReplacements) {
|
|
1986
|
+
// we changed the number of replacements which shifts remaining ones
|
|
1987
|
+
// since names won't match, we need to delete
|
|
1988
|
+
// all the remaining replacements and recreate them
|
|
1989
|
+
|
|
1990
|
+
let numberReplacementsLeft = workspace.numReplacementsBySource
|
|
1991
|
+
.slice(sourceNum)
|
|
1992
|
+
.reduce((a, c) => a + c, 0);
|
|
1993
|
+
|
|
1994
|
+
replacementInstruction.numberReplacementsToReplace =
|
|
1995
|
+
numberReplacementsLeft;
|
|
1996
|
+
|
|
1997
|
+
recreateRemaining = true;
|
|
1998
|
+
|
|
1999
|
+
// since deleted remaining, change in workspace
|
|
2000
|
+
// so that don't attempt to delete again
|
|
2001
|
+
workspace.numReplacementsBySource
|
|
2002
|
+
.slice(sourceNum)
|
|
2003
|
+
.forEach((v, i) => (workspace.numReplacementsBySource[i] = 0));
|
|
2004
|
+
workspace.numNonStringReplacementsBySource
|
|
2005
|
+
.slice(sourceNum)
|
|
2006
|
+
.forEach(
|
|
2007
|
+
(v, i) => (workspace.numNonStringReplacementsBySource[i] = 0),
|
|
2008
|
+
);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
replacementChanges.push(replacementInstruction);
|
|
2013
|
+
|
|
2014
|
+
continue;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
if (
|
|
2018
|
+
!effectivePropNameBySource[sourceNum] &&
|
|
2019
|
+
workspace.numReplacementsBySource[sourceNum] > 0
|
|
2020
|
+
) {
|
|
2021
|
+
// if previously had replacements and target still isn't inactive
|
|
2022
|
+
// then don't check for changes if don't have a propName
|
|
2023
|
+
numReplacementsSoFar += workspace.numReplacementsBySource[sourceNum];
|
|
2024
|
+
numNonStringReplacementsSoFar +=
|
|
2025
|
+
workspace.numNonStringReplacementsBySource[sourceNum];
|
|
2026
|
+
numReplacementsBySource[sourceNum] =
|
|
2027
|
+
workspace.numReplacementsBySource[sourceNum];
|
|
2028
|
+
numNonStringReplacementsBySource[sourceNum] =
|
|
2029
|
+
workspace.numNonStringReplacementsBySource[sourceNum];
|
|
2030
|
+
continue;
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
// use new uniqueIdentifiersUsed
|
|
2034
|
+
// so will get the same names for pieces that match
|
|
2035
|
+
let uniqueIdentifiersUsed = (workspace.uniqueIdentifiersUsedBySource[
|
|
2036
|
+
sourceNum
|
|
2037
|
+
] = []);
|
|
2038
|
+
|
|
2039
|
+
let results = await this.createReplacementForSource({
|
|
2040
|
+
component,
|
|
2041
|
+
sourceNum,
|
|
2042
|
+
components,
|
|
2043
|
+
numReplacementsSoFar,
|
|
2044
|
+
numNonStringReplacementsSoFar,
|
|
2045
|
+
uniqueIdentifiersUsed,
|
|
2046
|
+
compositeAttributesObj,
|
|
2047
|
+
componentInfoObjects,
|
|
2048
|
+
numComponentsForSource,
|
|
2049
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
2050
|
+
flags,
|
|
2051
|
+
});
|
|
2052
|
+
|
|
2053
|
+
let propVariablesCopiedByReplacement =
|
|
2054
|
+
results.propVariablesCopiedByReplacement;
|
|
2055
|
+
|
|
2056
|
+
let newSerializedReplacements = results.serializedReplacements;
|
|
2057
|
+
|
|
2058
|
+
let nNewReplacements = newSerializedReplacements.length;
|
|
2059
|
+
let nOldReplacements = workspace.numReplacementsBySource[sourceNum];
|
|
2060
|
+
|
|
2061
|
+
if (nNewReplacements !== nOldReplacements) {
|
|
2062
|
+
// changing the number of replacements will shift the remaining replacements
|
|
2063
|
+
// and change resulting names,
|
|
2064
|
+
// delete all remaining and mark to be recreated
|
|
2065
|
+
|
|
2066
|
+
let numberReplacementsLeft = workspace.numReplacementsBySource
|
|
2067
|
+
.slice(sourceNum)
|
|
2068
|
+
.reduce((a, c) => a + c, 0);
|
|
2069
|
+
|
|
2070
|
+
let replacementInstruction = {
|
|
2071
|
+
changeType: "add",
|
|
2072
|
+
changeTopLevelReplacements: true,
|
|
2073
|
+
firstReplacementInd: numReplacementsSoFar,
|
|
2074
|
+
numberReplacementsToReplace: numberReplacementsLeft,
|
|
2075
|
+
serializedReplacements: newSerializedReplacements,
|
|
2076
|
+
assignNamesOffset: numNonStringReplacementsSoFar,
|
|
2077
|
+
};
|
|
2078
|
+
|
|
2079
|
+
replacementChanges.push(replacementInstruction);
|
|
2080
|
+
|
|
2081
|
+
recreateRemaining = true;
|
|
2082
|
+
|
|
2083
|
+
// since deleted remaining, change in workspace
|
|
2084
|
+
// so that don't attempt to delete again
|
|
2085
|
+
workspace.numReplacementsBySource
|
|
2086
|
+
.slice(sourceNum)
|
|
2087
|
+
.forEach((v, i) => (workspace.numReplacementsBySource[i] = 0));
|
|
2088
|
+
workspace.numNonStringReplacementsBySource
|
|
2089
|
+
.slice(sourceNum)
|
|
2090
|
+
.forEach(
|
|
2091
|
+
(v, i) => (workspace.numNonStringReplacementsBySource[i] = 0),
|
|
2092
|
+
);
|
|
2093
|
+
} else {
|
|
2094
|
+
let nonStringInd = 0;
|
|
2095
|
+
for (let ind = 0; ind < nNewReplacements; ind++) {
|
|
2096
|
+
let foundDifference =
|
|
2097
|
+
propVariablesCopiedByReplacement[ind].length !==
|
|
2098
|
+
workspace.propVariablesCopiedBySource[sourceNum][ind].length;
|
|
2099
|
+
let onlyDifferenceIsType = !foundDifference;
|
|
2100
|
+
if (!foundDifference) {
|
|
2101
|
+
if (
|
|
2102
|
+
workspace.propVariablesCopiedBySource[sourceNum][ind].some(
|
|
2103
|
+
(v, i) => v !== propVariablesCopiedByReplacement[ind][i],
|
|
2104
|
+
)
|
|
2105
|
+
) {
|
|
2106
|
+
onlyDifferenceIsType = false;
|
|
2107
|
+
foundDifference = true;
|
|
2108
|
+
} else {
|
|
2109
|
+
if (
|
|
2110
|
+
component.replacements[numReplacementsSoFar + ind]
|
|
2111
|
+
.componentType !==
|
|
2112
|
+
newSerializedReplacements[ind].componentType
|
|
2113
|
+
) {
|
|
2114
|
+
foundDifference = true;
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
if (ind == 0 && foundDifference && onlyDifferenceIsType) {
|
|
2120
|
+
let requiredLength = await component.stateValues
|
|
2121
|
+
.numComponentsSpecified;
|
|
2122
|
+
|
|
2123
|
+
let wrapExistingReplacements =
|
|
2124
|
+
requiredLength === 1 &&
|
|
2125
|
+
nNewReplacements === 1 &&
|
|
2126
|
+
!(component.replacementsToWithhold > 0) &&
|
|
2127
|
+
workspace.sourceNames.length === 1;
|
|
2128
|
+
|
|
2129
|
+
if (wrapExistingReplacements) {
|
|
2130
|
+
foundDifference = false;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
if (foundDifference) {
|
|
2135
|
+
let replacementInstruction = {
|
|
2136
|
+
changeType: "add",
|
|
2137
|
+
changeTopLevelReplacements: true,
|
|
2138
|
+
firstReplacementInd: numReplacementsSoFar + ind,
|
|
2139
|
+
numberReplacementsToReplace: 1,
|
|
2140
|
+
serializedReplacements: [newSerializedReplacements[ind]],
|
|
2141
|
+
assignNamesOffset: numNonStringReplacementsSoFar + nonStringInd,
|
|
2142
|
+
};
|
|
2143
|
+
replacementChanges.push(replacementInstruction);
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
if (typeof newSerializedReplacements[ind] !== "string") {
|
|
2147
|
+
nonStringInd++;
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
let nNewNonStrings = newSerializedReplacements.filter(
|
|
2153
|
+
(x) => typeof x !== "string",
|
|
2154
|
+
).length;
|
|
2155
|
+
|
|
2156
|
+
numReplacementsSoFar += nNewReplacements;
|
|
2157
|
+
numNonStringReplacementsSoFar += nNewNonStrings;
|
|
2158
|
+
|
|
2159
|
+
numReplacementsBySource[sourceNum] = nNewReplacements;
|
|
2160
|
+
numNonStringReplacementsBySource[sourceNum] = nNewNonStrings;
|
|
2161
|
+
|
|
2162
|
+
propVariablesCopiedBySource[sourceNum] = propVariablesCopiedByReplacement;
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
let previousZeroSourceNames = workspace.sourceNames.length === 0;
|
|
2166
|
+
|
|
2167
|
+
workspace.numReplacementsBySource = numReplacementsBySource;
|
|
2168
|
+
workspace.numNonStringReplacementsBySource =
|
|
2169
|
+
numNonStringReplacementsBySource;
|
|
2170
|
+
workspace.sourceNames = replacementSourceIdentities.map(
|
|
2171
|
+
(x) => x.componentName,
|
|
2172
|
+
);
|
|
2173
|
+
workspace.propVariablesCopiedBySource = propVariablesCopiedBySource;
|
|
2174
|
+
|
|
2175
|
+
let verificationResult = await verifyReplacementsMatchSpecifiedType({
|
|
2176
|
+
component,
|
|
2177
|
+
replacementChanges,
|
|
2178
|
+
assignNames,
|
|
2179
|
+
workspace,
|
|
2180
|
+
componentInfoObjects,
|
|
2181
|
+
compositeAttributesObj,
|
|
2182
|
+
flags,
|
|
2183
|
+
});
|
|
2184
|
+
|
|
2185
|
+
// Note: this has to run after verify,
|
|
2186
|
+
// as verify has side effects of setting workspace variables,
|
|
2187
|
+
// such as numReplacementsBySource
|
|
2188
|
+
if (previousZeroSourceNames && workspace.sourceNames.length === 0) {
|
|
2189
|
+
// didn't have sources before and still don't have sources.
|
|
2190
|
+
// we're just getting filler components being recreated.
|
|
2191
|
+
// Don't actually make those changes
|
|
2192
|
+
return [];
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
// console.log("replacementChanges");
|
|
2196
|
+
// console.log(verificationResult.replacementChanges);
|
|
2197
|
+
|
|
2198
|
+
return verificationResult.replacementChanges;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
static async recreateReplacements({
|
|
2202
|
+
component,
|
|
2203
|
+
sourceNum,
|
|
2204
|
+
numReplacementsSoFar,
|
|
2205
|
+
numNonStringReplacementsSoFar,
|
|
2206
|
+
numReplacementsToDelete,
|
|
2207
|
+
uniqueIdentifiersUsed,
|
|
2208
|
+
components,
|
|
2209
|
+
compositeAttributesObj,
|
|
2210
|
+
componentInfoObjects,
|
|
2211
|
+
numComponentsForSource,
|
|
2212
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
2213
|
+
flags,
|
|
2214
|
+
}) {
|
|
2215
|
+
let results = await this.createReplacementForSource({
|
|
2216
|
+
component,
|
|
2217
|
+
sourceNum,
|
|
2218
|
+
numReplacementsSoFar,
|
|
2219
|
+
numNonStringReplacementsSoFar,
|
|
2220
|
+
components,
|
|
2221
|
+
uniqueIdentifiersUsed,
|
|
2222
|
+
compositeAttributesObj,
|
|
2223
|
+
componentInfoObjects,
|
|
2224
|
+
numComponentsForSource,
|
|
2225
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
2226
|
+
flags,
|
|
2227
|
+
});
|
|
2228
|
+
|
|
2229
|
+
let propVariablesCopiedByReplacement =
|
|
2230
|
+
results.propVariablesCopiedByReplacement;
|
|
2231
|
+
|
|
2232
|
+
let newSerializedChildren = results.serializedReplacements;
|
|
2233
|
+
|
|
2234
|
+
let replacementInstruction = {
|
|
2235
|
+
changeType: "add",
|
|
2236
|
+
changeTopLevelReplacements: true,
|
|
2237
|
+
firstReplacementInd: numReplacementsSoFar,
|
|
2238
|
+
numberReplacementsToReplace: numReplacementsToDelete,
|
|
2239
|
+
serializedReplacements: newSerializedChildren,
|
|
2240
|
+
assignNamesOffset: numNonStringReplacementsSoFar,
|
|
2241
|
+
};
|
|
2242
|
+
|
|
2243
|
+
return {
|
|
2244
|
+
numReplacements: newSerializedChildren.length,
|
|
2245
|
+
numNonStringReplacements: newSerializedChildren.filter(
|
|
2246
|
+
(x) => typeof x !== "string",
|
|
2247
|
+
).length,
|
|
2248
|
+
propVariablesCopiedByReplacement,
|
|
2249
|
+
replacementInstruction,
|
|
2250
|
+
};
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
export async function replacementFromProp({
|
|
2255
|
+
component,
|
|
2256
|
+
components,
|
|
2257
|
+
replacementSource,
|
|
2258
|
+
propName,
|
|
2259
|
+
// numReplacementsSoFar,
|
|
2260
|
+
uniqueIdentifiersUsed,
|
|
2261
|
+
compositeAttributesObj,
|
|
2262
|
+
componentInfoObjects,
|
|
2263
|
+
numComponentsForSource,
|
|
2264
|
+
publicCaseInsensitiveAliasSubstitutions,
|
|
2265
|
+
flags,
|
|
2266
|
+
}) {
|
|
2267
|
+
// console.log(`replacement from prop for ${component.componentName}`)
|
|
2268
|
+
// console.log(replacementSource)
|
|
2269
|
+
|
|
2270
|
+
let serializedReplacements = [];
|
|
2271
|
+
let propVariablesCopiedByReplacement = [];
|
|
2272
|
+
let newNamespace = component.attributes.newNamespace?.primitive;
|
|
2273
|
+
|
|
2274
|
+
// if (replacementSource === null) {
|
|
2275
|
+
// return { serializedReplacements, propVariablesCopiedByReplacement };
|
|
2276
|
+
// }
|
|
2277
|
+
|
|
2278
|
+
let replacementInd = -1; //numReplacementsSoFar - 1;
|
|
2279
|
+
|
|
2280
|
+
let target = components[replacementSource.componentName];
|
|
2281
|
+
|
|
2282
|
+
let varName = publicCaseInsensitiveAliasSubstitutions({
|
|
2283
|
+
stateVariables: [propName],
|
|
2284
|
+
componentClass: target.constructor,
|
|
2285
|
+
})[0];
|
|
2286
|
+
|
|
2287
|
+
if (varName === undefined || varName.slice(0, 12) === "__not_public") {
|
|
2288
|
+
if (propName !== "__prop_name_not_found") {
|
|
2289
|
+
console.warn(
|
|
2290
|
+
`Could not find prop ${propName} on a component of type ${replacementSource.componentType}`,
|
|
2291
|
+
);
|
|
2292
|
+
}
|
|
2293
|
+
return {
|
|
2294
|
+
serializedReplacements: [],
|
|
2295
|
+
propVariablesCopiedByReplacement: [],
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
let stateVarObj = target.state[varName];
|
|
2300
|
+
let stateVarValue = await stateVarObj.value;
|
|
2301
|
+
|
|
2302
|
+
let link = await component.stateValues.link;
|
|
2303
|
+
|
|
2304
|
+
if (stateVarObj.isArray || stateVarObj.isArrayEntry) {
|
|
2305
|
+
let arrayStateVarObj, unflattenedArrayKeys, arraySize, arrayKeys;
|
|
2306
|
+
if (stateVarObj.isArray) {
|
|
2307
|
+
arrayStateVarObj = stateVarObj;
|
|
2308
|
+
arraySize = await stateVarObj.arraySize;
|
|
2309
|
+
unflattenedArrayKeys = stateVarObj.getAllArrayKeys(arraySize, false);
|
|
2310
|
+
} else {
|
|
2311
|
+
arrayStateVarObj = target.state[stateVarObj.arrayStateVariable];
|
|
2312
|
+
unflattenedArrayKeys = await stateVarObj.unflattenedArrayKeys;
|
|
2313
|
+
arrayKeys = await stateVarObj.arrayKeys;
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
if (arrayStateVarObj.shadowingInstructions?.hasVariableComponentType) {
|
|
2317
|
+
await component.stateValues.replacementSources;
|
|
2318
|
+
if (!arrayStateVarObj.shadowingInstructions.createComponentOfType) {
|
|
2319
|
+
return {
|
|
2320
|
+
serializedReplacements: [],
|
|
2321
|
+
propVariablesCopiedByReplacement: [],
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
let wrappingComponents = stateVarObj.wrappingComponents;
|
|
2327
|
+
let numWrappingComponents = wrappingComponents.length;
|
|
2328
|
+
|
|
2329
|
+
let numReplacementsForSource = numComponentsForSource;
|
|
2330
|
+
|
|
2331
|
+
if (stateVarObj.isArray) {
|
|
2332
|
+
numReplacementsForSource = arraySize
|
|
2333
|
+
.slice(0, arraySize.length - numWrappingComponents)
|
|
2334
|
+
.reduce((a, c) => a * c, 1);
|
|
2335
|
+
} else {
|
|
2336
|
+
if (arrayKeys.length === 0) {
|
|
2337
|
+
// have an undefined array entry
|
|
2338
|
+
numReplacementsForSource = 0;
|
|
2339
|
+
} else if (numWrappingComponents === 0) {
|
|
2340
|
+
// with no wrapping components, will just output
|
|
2341
|
+
// one component for each component of the array
|
|
2342
|
+
numReplacementsForSource = arrayKeys.length;
|
|
2343
|
+
} else if (numWrappingComponents >= stateVarObj.numDimensions) {
|
|
2344
|
+
// if had an outer wrapping component, would just have a single component
|
|
2345
|
+
numReplacementsForSource = 1;
|
|
2346
|
+
} else if (numWrappingComponents === stateVarObj.numDimensions - 1) {
|
|
2347
|
+
// if the second from outer dimension is wrapped
|
|
2348
|
+
// then just count the number of entries in the original array
|
|
2349
|
+
numReplacementsForSource = unflattenedArrayKeys.length;
|
|
2350
|
+
} else {
|
|
2351
|
+
// if have at least two unwrapped dimensions,
|
|
2352
|
+
// flatten the array so that the entries counted are the outermost wrapped
|
|
2353
|
+
// Note: we need to create a 3D array entry to access this,
|
|
2354
|
+
// so this code is so far untested
|
|
2355
|
+
let nLevelsToFlatten =
|
|
2356
|
+
stateVarObj.numDimensions - numWrappingComponents - 1;
|
|
2357
|
+
numReplacementsForSource = flattenLevels(
|
|
2358
|
+
unflattenedArrayKeys,
|
|
2359
|
+
nLevelsToFlatten,
|
|
2360
|
+
).length;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
if (numWrappingComponents === 0) {
|
|
2365
|
+
// return flattened entries
|
|
2366
|
+
|
|
2367
|
+
let flattenedArrayKeys = flattenDeep(unflattenedArrayKeys);
|
|
2368
|
+
|
|
2369
|
+
for (let ind = 0; ind < numReplacementsForSource; ind++) {
|
|
2370
|
+
let arrayKey = flattenedArrayKeys[ind];
|
|
2371
|
+
|
|
2372
|
+
if (await component.stateValues.removeEmptyArrayEntries) {
|
|
2373
|
+
// check if value of replacmentSource is undefined or null
|
|
2374
|
+
// if so, skip
|
|
2375
|
+
|
|
2376
|
+
if (!arrayKey) {
|
|
2377
|
+
// skip because didn't match array key
|
|
2378
|
+
continue;
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
let arrayIndex = arrayStateVarObj.keyToIndex(arrayKey);
|
|
2382
|
+
if (!Array.isArray(arrayIndex)) {
|
|
2383
|
+
arrayIndex = [arrayIndex];
|
|
2384
|
+
}
|
|
2385
|
+
let propStateValue = await arrayStateVarObj.value;
|
|
2386
|
+
for (let ind2 of arrayIndex) {
|
|
2387
|
+
propStateValue = propStateValue[ind2];
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
if (propStateValue === undefined || propStateValue === null) {
|
|
2391
|
+
continue;
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
replacementInd++;
|
|
2396
|
+
let propVariablesCopied = (propVariablesCopiedByReplacement[
|
|
2397
|
+
replacementInd
|
|
2398
|
+
] = []);
|
|
2399
|
+
|
|
2400
|
+
let createComponentOfType =
|
|
2401
|
+
arrayStateVarObj.shadowingInstructions.createComponentOfType;
|
|
2402
|
+
if (Array.isArray(createComponentOfType)) {
|
|
2403
|
+
// TODO: multidimensional arrays?
|
|
2404
|
+
|
|
2405
|
+
if (createComponentOfType[arrayStateVarObj.keyToIndex(arrayKey)]) {
|
|
2406
|
+
createComponentOfType =
|
|
2407
|
+
createComponentOfType[arrayStateVarObj.keyToIndex(arrayKey)];
|
|
2408
|
+
} else {
|
|
2409
|
+
// TODO: better way to handle no match?
|
|
2410
|
+
createComponentOfType = createComponentOfType[0];
|
|
2411
|
+
}
|
|
2412
|
+
// if (stateVarObj.isArrayEntry) {
|
|
2413
|
+
// createComponentOfType = createComponentOfType[arrayStateVarObj.keyToIndex(arrayKey)];
|
|
2414
|
+
// } else {
|
|
2415
|
+
// createComponentOfType = createComponentOfType[ind];
|
|
2416
|
+
// }
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
if (arrayKey) {
|
|
2420
|
+
let propVariable =
|
|
2421
|
+
arrayStateVarObj.arrayVarNameFromArrayKey(arrayKey);
|
|
2422
|
+
|
|
2423
|
+
propVariablesCopied.push(propVariable);
|
|
2424
|
+
|
|
2425
|
+
let uniqueIdentifierBase =
|
|
2426
|
+
replacementSource.componentName + "|shadow|" + propVariable;
|
|
2427
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
2428
|
+
uniqueIdentifierBase,
|
|
2429
|
+
uniqueIdentifiersUsed,
|
|
2430
|
+
);
|
|
2431
|
+
|
|
2432
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
2433
|
+
attributes: component.attributes,
|
|
2434
|
+
componentType: createComponentOfType,
|
|
2435
|
+
componentInfoObjects,
|
|
2436
|
+
compositeAttributesObj,
|
|
2437
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
2438
|
+
flags,
|
|
2439
|
+
});
|
|
2440
|
+
|
|
2441
|
+
let attributeComponentsShadowingStateVariables;
|
|
2442
|
+
if (
|
|
2443
|
+
arrayStateVarObj.shadowingInstructions
|
|
2444
|
+
.addAttributeComponentsShadowingStateVariables
|
|
2445
|
+
) {
|
|
2446
|
+
attributeComponentsShadowingStateVariables = {};
|
|
2447
|
+
|
|
2448
|
+
for (let attrName in arrayStateVarObj.shadowingInstructions
|
|
2449
|
+
.addAttributeComponentsShadowingStateVariables) {
|
|
2450
|
+
let stateVariableToShadow =
|
|
2451
|
+
arrayStateVarObj.shadowingInstructions
|
|
2452
|
+
.addAttributeComponentsShadowingStateVariables[attrName]
|
|
2453
|
+
.stateVariableToShadow;
|
|
2454
|
+
|
|
2455
|
+
let sObj = target.state[stateVariableToShadow];
|
|
2456
|
+
if (sObj.isArray) {
|
|
2457
|
+
stateVariableToShadow = sObj.arrayVarNameFromArrayKey(arrayKey);
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
attributeComponentsShadowingStateVariables[attrName] = {
|
|
2461
|
+
stateVariableToShadow,
|
|
2462
|
+
};
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
let stateVariablesShadowingStateVariables;
|
|
2467
|
+
if (
|
|
2468
|
+
arrayStateVarObj.shadowingInstructions
|
|
2469
|
+
.addStateVariablesShadowingStateVariables
|
|
2470
|
+
) {
|
|
2471
|
+
stateVariablesShadowingStateVariables = {};
|
|
2472
|
+
|
|
2473
|
+
for (let attrName in arrayStateVarObj.shadowingInstructions
|
|
2474
|
+
.addStateVariablesShadowingStateVariables) {
|
|
2475
|
+
let stateVariableToShadow =
|
|
2476
|
+
arrayStateVarObj.shadowingInstructions
|
|
2477
|
+
.addStateVariablesShadowingStateVariables[attrName]
|
|
2478
|
+
.stateVariableToShadow;
|
|
2479
|
+
|
|
2480
|
+
let sObj = target.state[stateVariableToShadow];
|
|
2481
|
+
if (sObj.isArray) {
|
|
2482
|
+
stateVariableToShadow = sObj.arrayVarNameFromArrayKey(arrayKey);
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
stateVariablesShadowingStateVariables[attrName] = {
|
|
2486
|
+
stateVariableToShadow,
|
|
2487
|
+
};
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
if (link) {
|
|
2492
|
+
let attributesForReplacement = {};
|
|
2493
|
+
|
|
2494
|
+
if (attributeComponentsShadowingStateVariables) {
|
|
2495
|
+
let classOfComponentToCreate =
|
|
2496
|
+
componentInfoObjects.allComponentClasses[createComponentOfType];
|
|
2497
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
2498
|
+
|
|
2499
|
+
for (let attrName in attributeComponentsShadowingStateVariables) {
|
|
2500
|
+
let stateVariableToShadow =
|
|
2501
|
+
attributeComponentsShadowingStateVariables[attrName]
|
|
2502
|
+
.stateVariableToShadow;
|
|
2503
|
+
let attributeComponentType =
|
|
2504
|
+
attrObj[attrName]?.createComponentOfType;
|
|
2505
|
+
|
|
2506
|
+
if (attributeComponentType) {
|
|
2507
|
+
let shadowComponent = {
|
|
2508
|
+
componentType: attributeComponentType,
|
|
2509
|
+
downstreamDependencies: {
|
|
2510
|
+
[target.componentName]: [
|
|
2511
|
+
{
|
|
2512
|
+
compositeName: component.componentName,
|
|
2513
|
+
dependencyType: "referenceShadow",
|
|
2514
|
+
propVariable: stateVariableToShadow,
|
|
2515
|
+
},
|
|
2516
|
+
],
|
|
2517
|
+
},
|
|
2518
|
+
};
|
|
2519
|
+
|
|
2520
|
+
attributesForReplacement[attrName] = {
|
|
2521
|
+
component: shadowComponent,
|
|
2522
|
+
};
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
Object.assign(attributesForReplacement, attributesFromComposite);
|
|
2528
|
+
|
|
2529
|
+
serializedReplacements.push({
|
|
2530
|
+
componentType: createComponentOfType,
|
|
2531
|
+
attributes: attributesForReplacement,
|
|
2532
|
+
downstreamDependencies: {
|
|
2533
|
+
[replacementSource.componentName]: [
|
|
2534
|
+
{
|
|
2535
|
+
dependencyType: "referenceShadow",
|
|
2536
|
+
compositeName: component.componentName,
|
|
2537
|
+
propVariable,
|
|
2538
|
+
additionalStateVariableShadowing:
|
|
2539
|
+
stateVariablesShadowingStateVariables,
|
|
2540
|
+
},
|
|
2541
|
+
],
|
|
2542
|
+
},
|
|
2543
|
+
uniqueIdentifier,
|
|
2544
|
+
});
|
|
2545
|
+
} else {
|
|
2546
|
+
// no link
|
|
2547
|
+
|
|
2548
|
+
let attributesForReplacement = {};
|
|
2549
|
+
|
|
2550
|
+
if (attributeComponentsShadowingStateVariables) {
|
|
2551
|
+
let classOfComponentToCreate =
|
|
2552
|
+
componentInfoObjects.allComponentClasses[createComponentOfType];
|
|
2553
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
2554
|
+
|
|
2555
|
+
let additionalAttributes = {};
|
|
2556
|
+
for (let attrName in attributeComponentsShadowingStateVariables) {
|
|
2557
|
+
if (attrObj[attrName]?.createComponentOfType) {
|
|
2558
|
+
let vName =
|
|
2559
|
+
attributeComponentsShadowingStateVariables[attrName]
|
|
2560
|
+
.stateVariableToShadow;
|
|
2561
|
+
let attributeStateVarObj = target.state[vName];
|
|
2562
|
+
let attributeValue = await attributeStateVarObj.value;
|
|
2563
|
+
if (attributeStateVarObj.isArray) {
|
|
2564
|
+
// Assume attribute has same dimensions as original
|
|
2565
|
+
// TODO: multidimensional arrays?
|
|
2566
|
+
attributeValue =
|
|
2567
|
+
attributeValue[attributeStateVarObj.keyToIndex[arrayKey]];
|
|
2568
|
+
}
|
|
2569
|
+
if (!target.state[vName].usedDefault) {
|
|
2570
|
+
additionalAttributes[attrName] = attributeValue;
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
let attributesFromComponent = convertAttributesForComponentType({
|
|
2576
|
+
attributes: additionalAttributes,
|
|
2577
|
+
componentType: createComponentOfType,
|
|
2578
|
+
componentInfoObjects,
|
|
2579
|
+
flags,
|
|
2580
|
+
});
|
|
2581
|
+
|
|
2582
|
+
if (stateVarObj.shadowingInstructions.attributesToShadow) {
|
|
2583
|
+
for (let attrName of stateVarObj.shadowingInstructions
|
|
2584
|
+
.attributesToShadow) {
|
|
2585
|
+
if (target.attributes[attrName]?.component) {
|
|
2586
|
+
attributesFromComponent[attrName] = {
|
|
2587
|
+
component: await target.attributes[
|
|
2588
|
+
attrName
|
|
2589
|
+
]?.component.serialize({
|
|
2590
|
+
copyAll: true,
|
|
2591
|
+
copyVariants: true,
|
|
2592
|
+
}),
|
|
2593
|
+
};
|
|
2594
|
+
} else if (
|
|
2595
|
+
target.attributes[attrName]?.primitive !== undefined
|
|
2596
|
+
) {
|
|
2597
|
+
attributesFromComponent[attrName] = {
|
|
2598
|
+
primitive: JSON.parse(
|
|
2599
|
+
JSON.stringify(target.attributes[attrName].primitive),
|
|
2600
|
+
),
|
|
2601
|
+
};
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
Object.assign(attributesForReplacement, attributesFromComponent);
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
Object.assign(attributesForReplacement, attributesFromComposite);
|
|
2610
|
+
|
|
2611
|
+
let primaryEssentialStateVariable = "value";
|
|
2612
|
+
let componentClass =
|
|
2613
|
+
componentInfoObjects.allComponentClasses[createComponentOfType];
|
|
2614
|
+
if (componentClass.primaryEssentialStateVariable) {
|
|
2615
|
+
primaryEssentialStateVariable =
|
|
2616
|
+
componentClass.primaryEssentialStateVariable;
|
|
2617
|
+
} else if (componentClass.primaryStateVariableForDefinition) {
|
|
2618
|
+
primaryEssentialStateVariable =
|
|
2619
|
+
componentClass.primaryStateVariableForDefinition;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
let arrayIndex = arrayStateVarObj.keyToIndex(arrayKey);
|
|
2623
|
+
if (!Array.isArray(arrayIndex)) {
|
|
2624
|
+
arrayIndex = [arrayIndex];
|
|
2625
|
+
}
|
|
2626
|
+
let propStateValue = await arrayStateVarObj.value;
|
|
2627
|
+
for (let ind2 of arrayIndex) {
|
|
2628
|
+
propStateValue = propStateValue[ind2];
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
let serializedComponent = {
|
|
2632
|
+
componentType: createComponentOfType,
|
|
2633
|
+
attributes: attributesForReplacement,
|
|
2634
|
+
state: {
|
|
2635
|
+
[primaryEssentialStateVariable]: propStateValue,
|
|
2636
|
+
},
|
|
2637
|
+
uniqueIdentifier,
|
|
2638
|
+
};
|
|
2639
|
+
|
|
2640
|
+
serializedReplacements.push(serializedComponent);
|
|
2641
|
+
}
|
|
2642
|
+
} else {
|
|
2643
|
+
// didn't match an array key, so just add an empty component of createComponentOfType
|
|
2644
|
+
let uniqueIdentifierBase = createComponentOfType + "|empty";
|
|
2645
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
2646
|
+
uniqueIdentifierBase,
|
|
2647
|
+
uniqueIdentifiersUsed,
|
|
2648
|
+
);
|
|
2649
|
+
|
|
2650
|
+
serializedReplacements.push({
|
|
2651
|
+
componentType: createComponentOfType,
|
|
2652
|
+
uniqueIdentifier,
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
} else {
|
|
2657
|
+
// have wrapping components
|
|
2658
|
+
|
|
2659
|
+
let createReplacementPiece = async function (
|
|
2660
|
+
subArrayKeys,
|
|
2661
|
+
numDimensionsLeft,
|
|
2662
|
+
init = false,
|
|
2663
|
+
) {
|
|
2664
|
+
let pieces = [];
|
|
2665
|
+
let propVariablesCopiedByPiece = [];
|
|
2666
|
+
|
|
2667
|
+
if (numDimensionsLeft > 1) {
|
|
2668
|
+
// since numDimensionsLeft > 1, each component of subArray should be an array
|
|
2669
|
+
for (let subSubArrayKeys of subArrayKeys) {
|
|
2670
|
+
// recurse down to previous dimension
|
|
2671
|
+
let result = await createReplacementPiece(
|
|
2672
|
+
subSubArrayKeys,
|
|
2673
|
+
numDimensionsLeft - 1,
|
|
2674
|
+
);
|
|
2675
|
+
pieces.push(...result.pieces);
|
|
2676
|
+
propVariablesCopiedByPiece.push(
|
|
2677
|
+
...result.propVariablesCopiedByPiece,
|
|
2678
|
+
);
|
|
2679
|
+
}
|
|
2680
|
+
} else {
|
|
2681
|
+
// down to last piece
|
|
2682
|
+
for (let arrayKey of subArrayKeys) {
|
|
2683
|
+
let propVariable =
|
|
2684
|
+
arrayStateVarObj.arrayVarNameFromArrayKey(arrayKey);
|
|
2685
|
+
let propVariablesCopiedForThisPiece = [propVariable];
|
|
2686
|
+
|
|
2687
|
+
let uniqueIdentifierBase =
|
|
2688
|
+
replacementSource.componentName + "|shadow|" + propVariable;
|
|
2689
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
2690
|
+
uniqueIdentifierBase,
|
|
2691
|
+
uniqueIdentifiersUsed,
|
|
2692
|
+
);
|
|
2693
|
+
|
|
2694
|
+
let createComponentOfType =
|
|
2695
|
+
arrayStateVarObj.shadowingInstructions.createComponentOfType;
|
|
2696
|
+
if (Array.isArray(createComponentOfType)) {
|
|
2697
|
+
// TODO: multidimensional arrays?
|
|
2698
|
+
createComponentOfType =
|
|
2699
|
+
createComponentOfType[arrayStateVarObj.keyToIndex(arrayKey)];
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2702
|
+
let attributeComponentsShadowingStateVariables;
|
|
2703
|
+
if (
|
|
2704
|
+
arrayStateVarObj.shadowingInstructions
|
|
2705
|
+
.addAttributeComponentsShadowingStateVariables
|
|
2706
|
+
) {
|
|
2707
|
+
attributeComponentsShadowingStateVariables = {};
|
|
2708
|
+
|
|
2709
|
+
let attributeShadowingInfo =
|
|
2710
|
+
arrayStateVarObj.shadowingInstructions
|
|
2711
|
+
.addAttributeComponentsShadowingStateVariables;
|
|
2712
|
+
|
|
2713
|
+
for (let attrName in attributeShadowingInfo) {
|
|
2714
|
+
if (
|
|
2715
|
+
!attributeShadowingInfo[attrName].addToOuterIfWrappedArray
|
|
2716
|
+
) {
|
|
2717
|
+
let stateVariableToShadow =
|
|
2718
|
+
attributeShadowingInfo[attrName].stateVariableToShadow;
|
|
2719
|
+
|
|
2720
|
+
let sObj = target.state[stateVariableToShadow];
|
|
2721
|
+
if (sObj.isArray) {
|
|
2722
|
+
stateVariableToShadow =
|
|
2723
|
+
sObj.arrayVarNameFromArrayKey(arrayKey);
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
attributeComponentsShadowingStateVariables[attrName] = {
|
|
2727
|
+
stateVariableToShadow,
|
|
2728
|
+
};
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
let stateVariablesShadowingStateVariables;
|
|
2734
|
+
if (
|
|
2735
|
+
arrayStateVarObj.shadowingInstructions
|
|
2736
|
+
.addStateVariablesShadowingStateVariables
|
|
2737
|
+
) {
|
|
2738
|
+
stateVariablesShadowingStateVariables = {};
|
|
2739
|
+
|
|
2740
|
+
for (let attrName in arrayStateVarObj.shadowingInstructions
|
|
2741
|
+
.addStateVariablesShadowingStateVariables) {
|
|
2742
|
+
let stateVariableToShadow =
|
|
2743
|
+
arrayStateVarObj.shadowingInstructions
|
|
2744
|
+
.addStateVariablesShadowingStateVariables[attrName]
|
|
2745
|
+
.stateVariableToShadow;
|
|
2746
|
+
|
|
2747
|
+
let sObj = target.state[stateVariableToShadow];
|
|
2748
|
+
if (sObj.isArray) {
|
|
2749
|
+
stateVariableToShadow =
|
|
2750
|
+
sObj.arrayVarNameFromArrayKey(arrayKey);
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
stateVariablesShadowingStateVariables[attrName] = {
|
|
2754
|
+
stateVariableToShadow,
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
if (link) {
|
|
2760
|
+
let attributesForReplacement = {};
|
|
2761
|
+
|
|
2762
|
+
if (attributeComponentsShadowingStateVariables) {
|
|
2763
|
+
let classOfComponentToCreate =
|
|
2764
|
+
componentInfoObjects.allComponentClasses[
|
|
2765
|
+
createComponentOfType
|
|
2766
|
+
];
|
|
2767
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
2768
|
+
|
|
2769
|
+
for (let attrName in attributeComponentsShadowingStateVariables) {
|
|
2770
|
+
let stateVariableToShadow =
|
|
2771
|
+
attributeComponentsShadowingStateVariables[attrName]
|
|
2772
|
+
.stateVariableToShadow;
|
|
2773
|
+
let attributeComponentType =
|
|
2774
|
+
attrObj[attrName]?.createComponentOfType;
|
|
2775
|
+
|
|
2776
|
+
if (attributeComponentType) {
|
|
2777
|
+
let shadowComponent = {
|
|
2778
|
+
componentType: attributeComponentType,
|
|
2779
|
+
downstreamDependencies: {
|
|
2780
|
+
[target.componentName]: [
|
|
2781
|
+
{
|
|
2782
|
+
compositeName: component.componentName,
|
|
2783
|
+
dependencyType: "referenceShadow",
|
|
2784
|
+
propVariable: stateVariableToShadow,
|
|
2785
|
+
},
|
|
2786
|
+
],
|
|
2787
|
+
},
|
|
2788
|
+
};
|
|
2789
|
+
|
|
2790
|
+
attributesForReplacement[attrName] = {
|
|
2791
|
+
component: shadowComponent,
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
pieces.push({
|
|
2798
|
+
componentType: createComponentOfType,
|
|
2799
|
+
attributes: attributesForReplacement,
|
|
2800
|
+
downstreamDependencies: {
|
|
2801
|
+
[replacementSource.componentName]: [
|
|
2802
|
+
{
|
|
2803
|
+
dependencyType: "referenceShadow",
|
|
2804
|
+
compositeName: component.componentName,
|
|
2805
|
+
propVariable,
|
|
2806
|
+
additionalStateVariableShadowing:
|
|
2807
|
+
stateVariablesShadowingStateVariables,
|
|
2808
|
+
},
|
|
2809
|
+
],
|
|
2810
|
+
},
|
|
2811
|
+
uniqueIdentifier,
|
|
2812
|
+
});
|
|
2813
|
+
} else {
|
|
2814
|
+
let attributesForReplacement = {};
|
|
2815
|
+
|
|
2816
|
+
if (attributeComponentsShadowingStateVariables) {
|
|
2817
|
+
let classOfComponentToCreate =
|
|
2818
|
+
componentInfoObjects.allComponentClasses[
|
|
2819
|
+
createComponentOfType
|
|
2820
|
+
];
|
|
2821
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
2822
|
+
let additionalAttributes = {};
|
|
2823
|
+
for (let attrName in attributeComponentsShadowingStateVariables) {
|
|
2824
|
+
if (attrObj[attrName]?.createComponentOfType) {
|
|
2825
|
+
let vName =
|
|
2826
|
+
attributeComponentsShadowingStateVariables[attrName]
|
|
2827
|
+
.stateVariableToShadow;
|
|
2828
|
+
let attributeStateVarObj = target.state[vName];
|
|
2829
|
+
let attributeValue = await attributeStateVarObj.value;
|
|
2830
|
+
if (attributeStateVarObj.isArray) {
|
|
2831
|
+
// Assume attribute has same dimensions as original
|
|
2832
|
+
// TODO: multidimensional arrays?
|
|
2833
|
+
attributeValue =
|
|
2834
|
+
attributeValue[
|
|
2835
|
+
attributeStateVarObj.keyToIndex[arrayKey]
|
|
2836
|
+
];
|
|
2837
|
+
}
|
|
2838
|
+
if (!target.state[vName].usedDefault) {
|
|
2839
|
+
additionalAttributes[attrName] = attributeValue;
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
let attributesFromComponent = convertAttributesForComponentType(
|
|
2845
|
+
{
|
|
2846
|
+
attributes: additionalAttributes,
|
|
2847
|
+
componentType: createComponentOfType,
|
|
2848
|
+
componentInfoObjects,
|
|
2849
|
+
flags,
|
|
2850
|
+
},
|
|
2851
|
+
);
|
|
2852
|
+
|
|
2853
|
+
if (stateVarObj.shadowingInstructions.attributesToShadow) {
|
|
2854
|
+
for (let attrName of stateVarObj.shadowingInstructions
|
|
2855
|
+
.attributesToShadow) {
|
|
2856
|
+
if (target.attributes[attrName]?.component) {
|
|
2857
|
+
attributesFromComponent[attrName] = {
|
|
2858
|
+
component: await target.attributes[
|
|
2859
|
+
attrName
|
|
2860
|
+
]?.component.serialize({
|
|
2861
|
+
copyAll: true,
|
|
2862
|
+
copyVariants: true,
|
|
2863
|
+
}),
|
|
2864
|
+
};
|
|
2865
|
+
} else if (
|
|
2866
|
+
target.attributes[attrName]?.primitive !== undefined
|
|
2867
|
+
) {
|
|
2868
|
+
attributesFromComponent[attrName] = {
|
|
2869
|
+
primitive: JSON.parse(
|
|
2870
|
+
JSON.stringify(target.attributes[attrName].primitive),
|
|
2871
|
+
),
|
|
2872
|
+
};
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2877
|
+
Object.assign(
|
|
2878
|
+
attributesForReplacement,
|
|
2879
|
+
attributesFromComponent,
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
let primaryEssentialStateVariable = "value";
|
|
2884
|
+
let componentClass =
|
|
2885
|
+
componentInfoObjects.allComponentClasses[createComponentOfType];
|
|
2886
|
+
if (componentClass.primaryEssentialStateVariable) {
|
|
2887
|
+
primaryEssentialStateVariable =
|
|
2888
|
+
componentClass.primaryEssentialStateVariable;
|
|
2889
|
+
} else if (componentClass.primaryStateVariableForDefinition) {
|
|
2890
|
+
primaryEssentialStateVariable =
|
|
2891
|
+
componentClass.primaryStateVariableForDefinition;
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
let arrayIndex = arrayStateVarObj.keyToIndex(arrayKey);
|
|
2895
|
+
if (!Array.isArray(arrayIndex)) {
|
|
2896
|
+
arrayIndex = [arrayIndex];
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
let propStateValue = await arrayStateVarObj.value;
|
|
2900
|
+
for (let ind of arrayIndex) {
|
|
2901
|
+
propStateValue = propStateValue[ind];
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
let serializedComponent = {
|
|
2905
|
+
componentType: createComponentOfType,
|
|
2906
|
+
attributes: attributesForReplacement,
|
|
2907
|
+
state: {
|
|
2908
|
+
[primaryEssentialStateVariable]: propStateValue,
|
|
2909
|
+
},
|
|
2910
|
+
uniqueIdentifier,
|
|
2911
|
+
};
|
|
2912
|
+
|
|
2913
|
+
pieces.push(serializedComponent);
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
propVariablesCopiedByPiece.push(propVariablesCopiedForThisPiece);
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
// we wrap this dimension if have corresponding wrapping components
|
|
2921
|
+
let wrapCs = wrappingComponents[numDimensionsLeft - 1];
|
|
2922
|
+
if (pieces.length > 0 && wrapCs && wrapCs.length > 0) {
|
|
2923
|
+
for (let ind = wrapCs.length - 1; ind >= 0; ind--) {
|
|
2924
|
+
let wrapCT =
|
|
2925
|
+
typeof wrapCs[ind] === "object"
|
|
2926
|
+
? wrapCs[ind].componentType
|
|
2927
|
+
: wrapCs[ind];
|
|
2928
|
+
let uniqueIdentifierBase = wrapCT + "|wrapper";
|
|
2929
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
2930
|
+
uniqueIdentifierBase,
|
|
2931
|
+
uniqueIdentifiersUsed,
|
|
2932
|
+
);
|
|
2933
|
+
|
|
2934
|
+
let children = [];
|
|
2935
|
+
let attributes = {};
|
|
2936
|
+
|
|
2937
|
+
for (let p of pieces) {
|
|
2938
|
+
if (p.isAttribute) {
|
|
2939
|
+
let attr = p.isAttribute;
|
|
2940
|
+
delete p.isAttribute;
|
|
2941
|
+
attributes[attr] = { component: p };
|
|
2942
|
+
} else {
|
|
2943
|
+
children.push(p);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
pieces = [
|
|
2948
|
+
{
|
|
2949
|
+
componentType: wrapCT,
|
|
2950
|
+
children,
|
|
2951
|
+
attributes,
|
|
2952
|
+
uniqueIdentifier,
|
|
2953
|
+
skipSugar: true,
|
|
2954
|
+
},
|
|
2955
|
+
];
|
|
2956
|
+
if (typeof wrapCs[ind] === "object") {
|
|
2957
|
+
if (wrapCs[ind].doenetAttributes) {
|
|
2958
|
+
pieces[0].doenetAttributes = Object.assign(
|
|
2959
|
+
{},
|
|
2960
|
+
wrapCs[ind].doenetAttributes,
|
|
2961
|
+
);
|
|
2962
|
+
}
|
|
2963
|
+
if (wrapCs[ind].isAttribute) {
|
|
2964
|
+
pieces[0].isAttribute = wrapCs[ind].isAttribute;
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
propVariablesCopiedByPiece = [
|
|
2969
|
+
flattenDeep(propVariablesCopiedByPiece),
|
|
2970
|
+
];
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
if (
|
|
2974
|
+
init &&
|
|
2975
|
+
arrayStateVarObj.shadowingInstructions
|
|
2976
|
+
.addAttributeComponentsShadowingStateVariables
|
|
2977
|
+
) {
|
|
2978
|
+
let attributeComponentsShadowingStateVariables = {};
|
|
2979
|
+
|
|
2980
|
+
let attributeShadowingInfo =
|
|
2981
|
+
arrayStateVarObj.shadowingInstructions
|
|
2982
|
+
.addAttributeComponentsShadowingStateVariables;
|
|
2983
|
+
|
|
2984
|
+
for (let attrName in attributeShadowingInfo) {
|
|
2985
|
+
if (attributeShadowingInfo[attrName].addToOuterIfWrappedArray) {
|
|
2986
|
+
let stateVariableToShadow =
|
|
2987
|
+
attributeShadowingInfo[attrName].stateVariableToShadow;
|
|
2988
|
+
|
|
2989
|
+
attributeComponentsShadowingStateVariables[attrName] = {
|
|
2990
|
+
stateVariableToShadow,
|
|
2991
|
+
};
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
if (
|
|
2996
|
+
Object.keys(attributeComponentsShadowingStateVariables).length > 0
|
|
2997
|
+
) {
|
|
2998
|
+
for (let piece of pieces) {
|
|
2999
|
+
let attributesForReplacement = piece.attributes;
|
|
3000
|
+
if (!attributesForReplacement) {
|
|
3001
|
+
attributesForReplacement = piece.attributes = {};
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
let classOfComponentToCreate =
|
|
3005
|
+
componentInfoObjects.allComponentClasses[piece.componentType];
|
|
3006
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
3007
|
+
|
|
3008
|
+
if (link) {
|
|
3009
|
+
for (let attrName in attributeComponentsShadowingStateVariables) {
|
|
3010
|
+
let stateVariableToShadow =
|
|
3011
|
+
attributeComponentsShadowingStateVariables[attrName]
|
|
3012
|
+
.stateVariableToShadow;
|
|
3013
|
+
let attributeComponentType =
|
|
3014
|
+
attrObj[attrName]?.createComponentOfType;
|
|
3015
|
+
|
|
3016
|
+
if (attributeComponentType) {
|
|
3017
|
+
let shadowComponent = {
|
|
3018
|
+
componentType: attributeComponentType,
|
|
3019
|
+
downstreamDependencies: {
|
|
3020
|
+
[target.componentName]: [
|
|
3021
|
+
{
|
|
3022
|
+
compositeName: component.componentName,
|
|
3023
|
+
dependencyType: "referenceShadow",
|
|
3024
|
+
propVariable: stateVariableToShadow,
|
|
3025
|
+
},
|
|
3026
|
+
],
|
|
3027
|
+
},
|
|
3028
|
+
};
|
|
3029
|
+
|
|
3030
|
+
attributesForReplacement[attrName] = {
|
|
3031
|
+
component: shadowComponent,
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
} else {
|
|
3036
|
+
let additionalAttributes = {};
|
|
3037
|
+
for (let attrName in attributeComponentsShadowingStateVariables) {
|
|
3038
|
+
if (attrObj[attrName]?.createComponentOfType) {
|
|
3039
|
+
let vName =
|
|
3040
|
+
attributeComponentsShadowingStateVariables[attrName]
|
|
3041
|
+
.stateVariableToShadow;
|
|
3042
|
+
let attributeStateVarObj = target.state[vName];
|
|
3043
|
+
let attributeValue = await attributeStateVarObj.value;
|
|
3044
|
+
|
|
3045
|
+
if (!target.state[vName].usedDefault) {
|
|
3046
|
+
additionalAttributes[attrName] = attributeValue;
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
if (Object.keys(additionalAttributes).length > 0) {
|
|
3052
|
+
additionalAttributes = convertAttributesForComponentType({
|
|
3053
|
+
attributes: additionalAttributes,
|
|
3054
|
+
componentType: piece.componentType,
|
|
3055
|
+
componentInfoObjects,
|
|
3056
|
+
flags,
|
|
3057
|
+
});
|
|
3058
|
+
|
|
3059
|
+
Object.assign(attributesForReplacement, additionalAttributes);
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
return { pieces, propVariablesCopiedByPiece };
|
|
3067
|
+
};
|
|
3068
|
+
|
|
3069
|
+
let result = await createReplacementPiece(
|
|
3070
|
+
unflattenedArrayKeys,
|
|
3071
|
+
stateVarObj.numDimensions,
|
|
3072
|
+
true,
|
|
3073
|
+
);
|
|
3074
|
+
|
|
3075
|
+
let newReplacements = result.pieces;
|
|
3076
|
+
propVariablesCopiedByReplacement = result.propVariablesCopiedByPiece;
|
|
3077
|
+
|
|
3078
|
+
// add downstream dependencies and attributes to top level replacements
|
|
3079
|
+
// (which are wrappers, so didn't get downstream dependencies originally)
|
|
3080
|
+
for (let replacement of newReplacements) {
|
|
3081
|
+
if (typeof replacement !== "object") {
|
|
3082
|
+
continue;
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
if (!replacement.attributes) {
|
|
3086
|
+
replacement.attributes = {};
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
3090
|
+
attributes: component.attributes,
|
|
3091
|
+
componentType: replacement.componentType,
|
|
3092
|
+
componentInfoObjects,
|
|
3093
|
+
compositeAttributesObj,
|
|
3094
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
3095
|
+
flags,
|
|
3096
|
+
});
|
|
3097
|
+
|
|
3098
|
+
Object.assign(replacement.attributes, attributesFromComposite);
|
|
3099
|
+
|
|
3100
|
+
if (link) {
|
|
3101
|
+
replacement.downstreamDependencies = {
|
|
3102
|
+
[replacementSource.componentName]: [
|
|
3103
|
+
{
|
|
3104
|
+
dependencyType: "referenceShadow",
|
|
3105
|
+
compositeName: component.componentName,
|
|
3106
|
+
propVariable: varName,
|
|
3107
|
+
ignorePrimaryStateVariable: true,
|
|
3108
|
+
},
|
|
3109
|
+
],
|
|
3110
|
+
};
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
replacementInd += newReplacements.length;
|
|
3115
|
+
|
|
3116
|
+
serializedReplacements.push(...newReplacements);
|
|
3117
|
+
|
|
3118
|
+
if (newReplacements.length < numReplacementsForSource) {
|
|
3119
|
+
// we didn't create enough replacements,
|
|
3120
|
+
// which could happen if we have componentType and numComponentsSpecified set
|
|
3121
|
+
|
|
3122
|
+
// just create additional replacements,
|
|
3123
|
+
// even though they won't yet refer to the right dependencies
|
|
3124
|
+
|
|
3125
|
+
for (
|
|
3126
|
+
let ind = newReplacements.length;
|
|
3127
|
+
ind < numReplacementsForSource;
|
|
3128
|
+
ind++
|
|
3129
|
+
) {
|
|
3130
|
+
replacementInd++;
|
|
3131
|
+
propVariablesCopiedByReplacement[replacementInd] = [];
|
|
3132
|
+
|
|
3133
|
+
let createComponentOfType;
|
|
3134
|
+
let wrapCs = wrappingComponents[0];
|
|
3135
|
+
let wrapDoenetAttributes;
|
|
3136
|
+
if (wrapCs && wrapCs.length > 0) {
|
|
3137
|
+
if (typeof wrapCs[0] === "object") {
|
|
3138
|
+
createComponentOfType = wrapCs[0].componentType;
|
|
3139
|
+
wrapDoenetAttributes = Object.assign(
|
|
3140
|
+
{},
|
|
3141
|
+
wrapCs[0].doenetAttributes,
|
|
3142
|
+
);
|
|
3143
|
+
} else {
|
|
3144
|
+
createComponentOfType = wrapCs[0];
|
|
3145
|
+
}
|
|
3146
|
+
} else {
|
|
3147
|
+
createComponentOfType =
|
|
3148
|
+
arrayStateVarObj.shadowingInstructions.createComponentOfType;
|
|
3149
|
+
if (Array.isArray(createComponentOfType)) {
|
|
3150
|
+
// TODO: multidimensional arrays?
|
|
3151
|
+
if (stateVarObj.isArrayEntry) {
|
|
3152
|
+
createComponentOfType =
|
|
3153
|
+
createComponentOfType[
|
|
3154
|
+
arrayStateVarObj.keyToIndex(arrayKeys[ind])
|
|
3155
|
+
];
|
|
3156
|
+
} else {
|
|
3157
|
+
createComponentOfType = createComponentOfType[ind];
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
|
|
3162
|
+
// just add an empty component of createComponentOfType
|
|
3163
|
+
|
|
3164
|
+
let uniqueIdentifierBase = createComponentOfType + "|empty";
|
|
3165
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
3166
|
+
uniqueIdentifierBase,
|
|
3167
|
+
uniqueIdentifiersUsed,
|
|
3168
|
+
);
|
|
3169
|
+
|
|
3170
|
+
let newReplacement = {
|
|
3171
|
+
componentType: createComponentOfType,
|
|
3172
|
+
uniqueIdentifier,
|
|
3173
|
+
};
|
|
3174
|
+
if (wrapDoenetAttributes) {
|
|
3175
|
+
newReplacement.doenetAttributes = wrapDoenetAttributes;
|
|
3176
|
+
}
|
|
3177
|
+
serializedReplacements.push(newReplacement);
|
|
3178
|
+
}
|
|
3179
|
+
} else if (newReplacements > numReplacementsForSource) {
|
|
3180
|
+
throw Error(
|
|
3181
|
+
`Something went wrong when creating replacements for ${component.componentName} as we ended up with too many replacements`,
|
|
3182
|
+
);
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
} else {
|
|
3186
|
+
// not an array or array entry
|
|
3187
|
+
|
|
3188
|
+
if (stateVarObj.shadowingInstructions?.hasVariableComponentType) {
|
|
3189
|
+
// evaluate stateVarObj to make sure createComponentOfType is calculated and up-to-date
|
|
3190
|
+
await stateVarObj.value;
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
if (!stateVarObj.shadowingInstructions?.createComponentOfType) {
|
|
3194
|
+
return {
|
|
3195
|
+
serializedReplacements: [],
|
|
3196
|
+
propVariablesCopiedByReplacement: [],
|
|
3197
|
+
};
|
|
3198
|
+
}
|
|
3199
|
+
|
|
3200
|
+
replacementInd++;
|
|
3201
|
+
|
|
3202
|
+
let propVariablesCopied = (propVariablesCopiedByReplacement[
|
|
3203
|
+
replacementInd
|
|
3204
|
+
] = []);
|
|
3205
|
+
|
|
3206
|
+
propVariablesCopied.push(varName);
|
|
3207
|
+
|
|
3208
|
+
let uniqueIdentifierBase = target.componentName + "|shadow|" + varName;
|
|
3209
|
+
let uniqueIdentifier = getUniqueIdentifierFromBase(
|
|
3210
|
+
uniqueIdentifierBase,
|
|
3211
|
+
uniqueIdentifiersUsed,
|
|
3212
|
+
);
|
|
3213
|
+
|
|
3214
|
+
if (stateVarObj.shadowingInstructions.createComponentOfType === "string") {
|
|
3215
|
+
serializedReplacements.push(await stateVarObj.value);
|
|
3216
|
+
} else {
|
|
3217
|
+
let attributesFromComposite = convertAttributesForComponentType({
|
|
3218
|
+
attributes: component.attributes,
|
|
3219
|
+
componentType: stateVarObj.shadowingInstructions.createComponentOfType,
|
|
3220
|
+
componentInfoObjects,
|
|
3221
|
+
compositeAttributesObj,
|
|
3222
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
3223
|
+
flags,
|
|
3224
|
+
});
|
|
3225
|
+
|
|
3226
|
+
if (link) {
|
|
3227
|
+
let attributesForReplacement = {};
|
|
3228
|
+
|
|
3229
|
+
if (
|
|
3230
|
+
stateVarObj.shadowingInstructions
|
|
3231
|
+
.addAttributeComponentsShadowingStateVariables
|
|
3232
|
+
) {
|
|
3233
|
+
let classOfComponentToCreate =
|
|
3234
|
+
componentInfoObjects.allComponentClasses[
|
|
3235
|
+
stateVarObj.shadowingInstructions.createComponentOfType
|
|
3236
|
+
];
|
|
3237
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
3238
|
+
|
|
3239
|
+
for (let attrName in stateVarObj.shadowingInstructions
|
|
3240
|
+
.addAttributeComponentsShadowingStateVariables) {
|
|
3241
|
+
let stateVariableToShadow =
|
|
3242
|
+
stateVarObj.shadowingInstructions
|
|
3243
|
+
.addAttributeComponentsShadowingStateVariables[attrName]
|
|
3244
|
+
.stateVariableToShadow;
|
|
3245
|
+
let attributeComponentType =
|
|
3246
|
+
attrObj[attrName]?.createComponentOfType;
|
|
3247
|
+
|
|
3248
|
+
if (attributeComponentType) {
|
|
3249
|
+
let shadowComponent = {
|
|
3250
|
+
componentType: attributeComponentType,
|
|
3251
|
+
downstreamDependencies: {
|
|
3252
|
+
[target.componentName]: [
|
|
3253
|
+
{
|
|
3254
|
+
compositeName: component.componentName,
|
|
3255
|
+
dependencyType: "referenceShadow",
|
|
3256
|
+
propVariable: stateVariableToShadow,
|
|
3257
|
+
},
|
|
3258
|
+
],
|
|
3259
|
+
},
|
|
3260
|
+
};
|
|
3261
|
+
|
|
3262
|
+
attributesForReplacement[attrName] = {
|
|
3263
|
+
component: shadowComponent,
|
|
3264
|
+
};
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
|
|
3269
|
+
Object.assign(attributesForReplacement, attributesFromComposite);
|
|
3270
|
+
|
|
3271
|
+
serializedReplacements.push({
|
|
3272
|
+
componentType:
|
|
3273
|
+
stateVarObj.shadowingInstructions.createComponentOfType,
|
|
3274
|
+
attributes: attributesForReplacement,
|
|
3275
|
+
downstreamDependencies: {
|
|
3276
|
+
[target.componentName]: [
|
|
3277
|
+
{
|
|
3278
|
+
dependencyType: "referenceShadow",
|
|
3279
|
+
compositeName: component.componentName,
|
|
3280
|
+
propVariable: varName,
|
|
3281
|
+
additionalStateVariableShadowing:
|
|
3282
|
+
stateVarObj.shadowingInstructions
|
|
3283
|
+
.addStateVariablesShadowingStateVariables,
|
|
3284
|
+
},
|
|
3285
|
+
],
|
|
3286
|
+
},
|
|
3287
|
+
uniqueIdentifier,
|
|
3288
|
+
});
|
|
3289
|
+
} else {
|
|
3290
|
+
let attributesForReplacement = {};
|
|
3291
|
+
|
|
3292
|
+
if (
|
|
3293
|
+
stateVarObj.shadowingInstructions
|
|
3294
|
+
.addAttributeComponentsShadowingStateVariables
|
|
3295
|
+
) {
|
|
3296
|
+
let classOfComponentToCreate =
|
|
3297
|
+
componentInfoObjects.allComponentClasses[
|
|
3298
|
+
stateVarObj.shadowingInstructions.createComponentOfType
|
|
3299
|
+
];
|
|
3300
|
+
let attrObj = classOfComponentToCreate.createAttributesObject();
|
|
3301
|
+
|
|
3302
|
+
let additionalAttributes = {};
|
|
3303
|
+
for (let attrName in stateVarObj.shadowingInstructions
|
|
3304
|
+
.addAttributeComponentsShadowingStateVariables) {
|
|
3305
|
+
if (attrObj[attrName]?.createComponentOfType) {
|
|
3306
|
+
// when copying with link=false, don't copy fixed attribute
|
|
3307
|
+
// so that, for example, a copy from a sequence with link=false is not fixed
|
|
3308
|
+
if (attrName !== "fixed") {
|
|
3309
|
+
let vName =
|
|
3310
|
+
stateVarObj.shadowingInstructions
|
|
3311
|
+
.addAttributeComponentsShadowingStateVariables[attrName]
|
|
3312
|
+
.stateVariableToShadow;
|
|
3313
|
+
let attributeValue = await target.state[vName].value;
|
|
3314
|
+
if (!target.state[vName].usedDefault) {
|
|
3315
|
+
additionalAttributes[attrName] = attributeValue;
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
let attributesFromComponent = convertAttributesForComponentType({
|
|
3322
|
+
attributes: additionalAttributes,
|
|
3323
|
+
componentType:
|
|
3324
|
+
stateVarObj.shadowingInstructions.createComponentOfType,
|
|
3325
|
+
componentInfoObjects,
|
|
3326
|
+
flags,
|
|
3327
|
+
});
|
|
3328
|
+
|
|
3329
|
+
if (stateVarObj.shadowingInstructions.attributesToShadow) {
|
|
3330
|
+
for (let attrName of stateVarObj.shadowingInstructions
|
|
3331
|
+
.attributesToShadow) {
|
|
3332
|
+
if (target.attributes[attrName]?.component) {
|
|
3333
|
+
attributesFromComponent[attrName] = {
|
|
3334
|
+
component: await target.attributes[
|
|
3335
|
+
attrName
|
|
3336
|
+
]?.component.serialize({ copyAll: true, copyVariants: true }),
|
|
3337
|
+
};
|
|
3338
|
+
} else if (target.attributes[attrName]?.primitive !== undefined) {
|
|
3339
|
+
attributesFromComponent[attrName] = {
|
|
3340
|
+
primitive: JSON.parse(
|
|
3341
|
+
JSON.stringify(target.attributes[attrName].primitive),
|
|
3342
|
+
),
|
|
3343
|
+
};
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
|
|
3348
|
+
Object.assign(attributesForReplacement, attributesFromComponent);
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
Object.assign(attributesForReplacement, attributesFromComposite);
|
|
3352
|
+
|
|
3353
|
+
let primaryEssentialStateVariable = "value";
|
|
3354
|
+
let componentClass =
|
|
3355
|
+
componentInfoObjects.allComponentClasses[
|
|
3356
|
+
stateVarObj.shadowingInstructions.createComponentOfType
|
|
3357
|
+
];
|
|
3358
|
+
if (componentClass.primaryEssentialStateVariable) {
|
|
3359
|
+
primaryEssentialStateVariable =
|
|
3360
|
+
componentClass.primaryEssentialStateVariable;
|
|
3361
|
+
} else if (componentClass.primaryStateVariableForDefinition) {
|
|
3362
|
+
primaryEssentialStateVariable =
|
|
3363
|
+
componentClass.primaryStateVariableForDefinition;
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
let serializedComponent = {
|
|
3367
|
+
componentType:
|
|
3368
|
+
stateVarObj.shadowingInstructions.createComponentOfType,
|
|
3369
|
+
attributes: attributesForReplacement,
|
|
3370
|
+
state: {
|
|
3371
|
+
[primaryEssentialStateVariable]: stateVarValue,
|
|
3372
|
+
},
|
|
3373
|
+
uniqueIdentifier,
|
|
3374
|
+
};
|
|
3375
|
+
|
|
3376
|
+
serializedReplacements.push(serializedComponent);
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3380
|
+
|
|
3381
|
+
if (await component.stateValues.isPlainMacro) {
|
|
3382
|
+
for (let repl of serializedReplacements) {
|
|
3383
|
+
if (!repl.doenetAttributes) {
|
|
3384
|
+
repl.doenetAttributes = {};
|
|
3385
|
+
}
|
|
3386
|
+
repl.doenetAttributes.fromPlainMacro = true;
|
|
3387
|
+
if (repl.downstreamDependencies?.[target.componentName]?.[0]) {
|
|
3388
|
+
repl.downstreamDependencies[
|
|
3389
|
+
target.componentName
|
|
3390
|
+
][0].fromPlainMacro = true;
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
} else if (await component.stateValues.isPlainCopy) {
|
|
3394
|
+
for (let repl of serializedReplacements) {
|
|
3395
|
+
if (!repl.doenetAttributes) {
|
|
3396
|
+
repl.doenetAttributes = {};
|
|
3397
|
+
}
|
|
3398
|
+
repl.doenetAttributes.fromPlainCopy = true;
|
|
3399
|
+
if (repl.downstreamDependencies?.[target.componentName]?.[0]) {
|
|
3400
|
+
repl.downstreamDependencies[
|
|
3401
|
+
target.componentName
|
|
3402
|
+
][0].fromPlainCopy = true;
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
|
|
3407
|
+
// console.log(`serializedReplacements for ${component.componentName}`)
|
|
3408
|
+
// console.log(JSON.parse(JSON.stringify(serializedReplacements)))
|
|
3409
|
+
// console.log(serializedReplacements)
|
|
3410
|
+
|
|
3411
|
+
return { serializedReplacements, propVariablesCopiedByReplacement };
|
|
3412
|
+
}
|