You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Several attributes are declared createComponentOfType: "_componentWithSelectableType", and the reference docs print that name verbatim as the attribute's type. _componentWithSelectableType is an internal abstract component; it tells an author nothing about what to write.
The value's type is resolved at sugar time by ComponentWithSelectableType: its own type attribute, else the parent'stype attribute, else the default number. So when the author does not state a type, the value is parsed as a number — even when everything around it is text.
That silently produces wrong answers rather than an error:
The last line reports indexOf did not find NaN among its values — the target was parsed as a number, became NaN, and matched nothing. The NaN in that message is the only visible trace of the cause. The <searchSorted> line gives no diagnostic at all: it returns 1, a perfectly plausible position.
The type an author needs is not always the type attribute
For the index operators the target has to match the type of the list entries, which is usually decided by the children — a referenced <textList>, say — and not by a type attribute at all. type exists to say how bare string children should be read; it happens to double as the target's type because ComponentWithSelectableType falls back to the parent's type. Those two jobs coincide often enough to be confusing and diverge often enough to be wrong.
There is no way to look up the resolved type
Of the nine components, only <substitute> exposes a public type property. The other eight have a typeattribute but no readable property, so an author cannot inspect what was chosen:
Most of these declare type with createPrimitiveOfType: "string" and no public: true, which is why it never becomes a property.
Possible directions
Not a proposal — the right fix probably combines several of these:
Render a meaningful label in the docs. Map _componentWithSelectableType to something like number, math, text, or boolean — follows this component's type instead of leaking the internal name. Cheapest fix, and it addresses the reported symptom.
Make type readable. Mark the type state variable public on the components that have one, so $seq.type works and matches <substitute>. Note the docs would then also need the attribute to explain what it governs.
Infer the type from the entries where the entries define it. For the index operators, deriving the target's type from the children would make <indexOf target="fig">$words</indexOf> simply work. This is the part that goes beyond wording.
Diagnose the mismatch. Where inference is not wanted, warn when a target parses to NaN against a list that is not numeric — the case above is currently silent for <searchSorted>.
Declare the valid values of type, so autocomplete offers them. Five components accept a type but declare no values for it, so the editor can suggest nothing and the docs show no value table. The set they accept is already known — the shared sugar warns (doenet-w0014) on anything outside math, text, number, boolean — it is simply not declared.
The ones that declare values use createComponentOfType with validValues; the ones that do not use a bare createPrimitiveOfType: "string". packages/lsp-tools/src/auto-completer/index.ts reads a.values for attribute-value completion, so declaring them is what makes the editor offer them. This is the smallest and most independent item here — it needs no decision about how the selectable type is resolved.
Done for the five in Add list operators: cumulative scans and list indices #1824 (<sort>, <shuffle>, <sortIndices>, <indexOf>, <searchSorted>, plus <argMin> and <argMax>), which all now declare number, math, text and boolean. <slider>, <substitute>, <updateValue> and the sequence family already declared theirs, so this direction is complete unless a component is found that still does not.
Give the schema a way to express it. An attribute whose type is "the resolved type of this component" is a real concept the schema cannot currently state; several of the above become easier if it can.
Scope
Nine components, the docs type-rendering pipeline, and possibly schema generation. Deliberately not addressed in #1824, which introduced <indexOf> and <searchSorted>: their target matches what <sequence> and the others already do, and changing that convention belongs in one change across all of them rather than for two new components alone.
Problem
Several attributes are declared
createComponentOfType: "_componentWithSelectableType", and the reference docs print that name verbatim as the attribute's type._componentWithSelectableTypeis an internal abstract component; it tells an author nothing about what to write.It affects 15 attributes across 9 components:
<sequence>,<selectFromSequence>,<repeatForSequence>,<animateFromSequence>from,to<slider>bindValueTo,initialValue<substitute>match,replacement<updateValue>newValue<indexOf>,<searchSorted>targetWhy it is more than a wording problem
The value's type is resolved at sugar time by
ComponentWithSelectableType: its owntypeattribute, else the parent'stypeattribute, else the defaultnumber. So when the author does not state atype, the value is parsed as a number — even when everything around it is text.That silently produces wrong answers rather than an error:
The last line reports
indexOf did not findNaNamong its values— the target was parsed as a number, becameNaN, and matched nothing. TheNaNin that message is the only visible trace of the cause. The<searchSorted>line gives no diagnostic at all: it returns 1, a perfectly plausible position.The type an author needs is not always the
typeattributeFor the index operators the target has to match the type of the list entries, which is usually decided by the children — a referenced
<textList>, say — and not by atypeattribute at all.typeexists to say how bare string children should be read; it happens to double as the target's type becauseComponentWithSelectableTypefalls back to the parent'stype. Those two jobs coincide often enough to be confusing and diverge often enough to be wrong.There is no way to look up the resolved type
Of the nine components, only
<substitute>exposes a publictypeproperty. The other eight have atypeattribute but no readable property, so an author cannot inspect what was chosen:typeattributetypeproperty<substitute><sequence>,<selectFromSequence>,<repeatForSequence>,<animateFromSequence>,<slider>,<updateValue>,<indexOf>,<searchSorted>Most of these declare
typewithcreatePrimitiveOfType: "string"and nopublic: true, which is why it never becomes a property.Possible directions
Not a proposal — the right fix probably combines several of these:
Render a meaningful label in the docs. Map
_componentWithSelectableTypeto something like number, math, text, or boolean — follows this component'stypeinstead of leaking the internal name. Cheapest fix, and it addresses the reported symptom.Make
typereadable. Mark thetypestate variablepublicon the components that have one, so$seq.typeworks and matches<substitute>. Note the docs would then also need the attribute to explain what it governs.Infer the type from the entries where the entries define it. For the index operators, deriving the target's type from the children would make
<indexOf target="fig">$words</indexOf>simply work. This is the part that goes beyond wording.Diagnose the mismatch. Where inference is not wanted, warn when a target parses to
NaNagainst a list that is not numeric — the case above is currently silent for<searchSorted>.Declare the valid values of
type, so autocomplete offers them. Five components accept atypebut declare no values for it, so the editor can suggest nothing and the docs show no value table. The set they accept is already known — the shared sugar warns (doenet-w0014) on anything outsidemath,text,number,boolean— it is simply not declared.typedeclares its valuestypedeclares nothing<sequence>,<selectFromSequence>,<repeatForSequence>,<animateFromSequence>(number,math,letters);<slider>(number,text);<substitute>(math,text);<updateValue>(math,number,boolean,text)<sort>,<shuffle>,<sortIndices>,<indexOf>,<searchSorted>The ones that declare values use
createComponentOfTypewithvalidValues; the ones that do not use a barecreatePrimitiveOfType: "string".packages/lsp-tools/src/auto-completer/index.tsreadsa.valuesfor attribute-value completion, so declaring them is what makes the editor offer them. This is the smallest and most independent item here — it needs no decision about how the selectable type is resolved.Done for the five in Add list operators: cumulative scans and list indices #1824 (
<sort>,<shuffle>,<sortIndices>,<indexOf>,<searchSorted>, plus<argMin>and<argMax>), which all now declarenumber,math,textandboolean.<slider>,<substitute>,<updateValue>and the sequence family already declared theirs, so this direction is complete unless a component is found that still does not.Give the schema a way to express it. An attribute whose type is "the resolved type of this component" is a real concept the schema cannot currently state; several of the above become easier if it can.
Scope
Nine components, the docs type-rendering pipeline, and possibly schema generation. Deliberately not addressed in #1824, which introduced
<indexOf>and<searchSorted>: theirtargetmatches what<sequence>and the others already do, and changing that convention belongs in one change across all of them rather than for two new components alone.🤖 Generated with Claude Code
https://claude.ai/code/session_01JMbAScbaa3RtikSh9C3qam