@doenet/v06-to-v07 0.7.21-dev.364 → 0.7.21-dev.367

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.
@@ -42591,7 +42591,7 @@ async function cidFromArrayBuffer(data) {
42591
42591
  await crypto.subtle.digest("SHA-256", new Uint8Array());
42592
42592
  digest = (data2) => crypto.subtle.digest("SHA-256", data2);
42593
42593
  } catch (e22) {
42594
- const sha256 = (await import("./sha256-1m3pbIuR-CcR_uzOg-DFbzNMx_.js").then((n2) => n2.s)).default;
42594
+ const sha256 = (await import("./sha256-1m3pbIuR-doXkfhnK-DnBnHZ9g.js").then((n2) => n2.s)).default;
42595
42595
  digest = (data2) => sha256(data2, {
42596
42596
  asBytes: true
42597
42597
  });
@@ -46357,7 +46357,7 @@ class Indent {
46357
46357
  }
46358
46358
  const chrome$1 = "# Viewer chrome: buttons, panel headers, and other UI the reader interacts\n# with. Rendered on the main thread and selected by `uiLocale`.\n#\n# Message ids are lower-kebab-case Fluent identifiers, optionally with a\n# single `.attribute` suffix (`submit-button`, `answer-status.correct`).\n#\n# This catalog is the source of truth for every other locale: `lint:i18n`\n# rejects a translation that defines a key missing here. Run\n# `npm run codegen -w @doenet/i18n` after editing.\n\n\n## Answer submission — the check-work button and the status it reports.\n\nanswer-checking = Checking...\nanswer-submitting = Submitting...\n\n# Announced to a screen reader while the submission is in flight. Separate\n# from the button's own text, which is abbreviated.\nanswer-checking-status = Checking answer\nanswer-submitting-status = Submitting answer\n\nanswer-correct = Correct\nanswer-incorrect = Incorrect\n\n# Shown instead of a correctness verdict when the activity withholds\n# correctness: the response was recorded, nothing is claimed about it.\nanswer-response-saved = Response Saved\n\n# Partial credit. `-credit` is used when repeated attempts reduce the credit\n# available, `-correct` when they do not, and `-short` on a button too narrow\n# for a word.\nanswer-percent-credit = { $percent }% Credit\nanswer-percent-correct = { $percent }% Correct\nanswer-percent-short = { $percent } %\n\nmax-credit-available = Max credit available: { $percent }%\n\n# Fluent formats `{ $count }` with `Intl.NumberFormat`, so a four-digit\n# attempt count renders as \"1,000\" where the hand-built string said \"1000\".\n# That is the one place English output is not byte-identical to what this\n# replaced, and grouping is the locale-correct rendering, so it stands.\nattempts-remaining =\n { $count ->\n [0] no attempts remaining\n [one] { $count } attempt remaining\n *[other] { $count } attempts remaining\n }\n\n# Appended to an input's accessible name once its response has been graded,\n# so a screen reader reports the verdict along with the field.\nvalidation-correct = (Correct)\nvalidation-incorrect = (Incorrect)\nvalidation-partially-correct = (Partially correct)\n\n# Tooltip on the badge that reports how many responses have been submitted to\n# one answer, shown only to a host that asked for it. `$answerId` is the\n# answer's authored name and is never translated.\nanswer-show-responses =\n { $count ->\n [one] Show { $count } response to { $answerId }\n *[other] Show { $count } responses to { $answerId }\n }\n\n\n## Disclosure panels\n\nfeedback-heading = Feedback\n\n# Follows a disclosure panel's own heading — \"Solution (click to open)\" — and\n# is shared by `<solution>`, `<hint>`, and a collapsible `<section>`. The whole\n# parenthetical is one message: where the word for open or close falls inside\n# it is the translator's business.\ncollapsible-click-to-open = (click to open)\ncollapsible-click-to-close = (click to close)\n\n# Placeholder inside a panel that has been opened before its contents have\n# arrived from the core. Shared by `<solution>` and a collapsible `<section>`.\ncollapsible-initializing = Initializing...\n\n# Tooltip on a footnote marker, naming what activating it will do.\nfootnote-show = Show footnote\nfootnote-hide = Hide footnote\n\n# Tooltip on the ⓘ affordance that reveals an input's description.\ndescription-more-information = more information\n\n\n## Controls\n\nslider-previous = Prev\nslider-next = Next\n\nkeyboard-open = Open Keyboard\nkeyboard-close = Close Keyboard\n\n# Accessible names of a matrix input's size controls, whose visible labels are\n# the symbols `r-` `r+` `c-` `c+`.\nmatrix-remove-row = Remove row\nmatrix-add-row = Add row\nmatrix-remove-column = Remove column\nmatrix-add-column = Add column\n\n# Modes and actions of the subset-of-reals input's control strip. The button\n# that selects all of the reals is the symbol `R`, not a word, and stays in\n# place.\nsubset-add-remove-points = Add/Remove points\nsubset-toggle-points-intervals = Toggle points and intervals\nsubset-move-points = Move Points\nsubset-clear = Clear\n\n# Buttons that edit an orbital diagram: rows hold boxes, boxes hold up to\n# three spin arrows.\norbital-add-row = Add Row\norbital-remove-row = Remove Row\norbital-add-box = Add Box\norbital-remove-box = Remove Box\norbital-add-up-arrow = Add Up Arrow\norbital-add-down-arrow = Add Down Arrow\norbital-remove-arrow = Remove Arrow\n\n# Accessible name of the text field naming one row of an orbital diagram,\n# counting from 1.\norbital-row-label = Label for row { $row }\n\n# Labels the answer column of a pretzel exercise's grid.\npretzel-answer = Answer\n\n# Caption above the table a `<summaryStatistics>` renders. `$column` is the\n# authored name of the data column being summarized and is never translated.\n# The table's own headings (`mean`, `stdev`, `quartile1`, …) are the statistic\n# ids an author references, not prose, and stay in place.\nsummary-statistics-caption = Summary statistics of { $column }\n\n\n## Math input\n\n# Accessible name of the popover that previews the typed expression, and of\n# the rendered expression inside it.\nmath-input-preview-region = math expression preview\nmath-input-preview = Preview\nmath-input-invalid-expression = Invalid expression:\n\n\n## Document status\n\n# Shown while the core is still starting up and nothing can be rendered yet.\nviewer-initializing = Initializing...\n\n\n## Errors\n\n# Prefixes an error message wherever one is shown in place of content: an\n# `<error>` the core reported, the error boundary's fallback, and the\n# placeholder left where a renderer chunk failed to load.\nerror-heading = Error\n\n# Banner above a document that compiled with at least one error in it.\ndocument-contains-errors = This document contains errors!\n\n# Shown in place of the document when a renderer threw and the error boundary\n# caught it.\nsomething-went-wrong = Something went wrong.\n\n# Shown in place of a single renderer whose code chunk never arrived.\nrenderer-load-failed = a renderer failed to load. Please reload the page.\n\n# Shown in place of the document when the core worker could not be started\n# after retries, rather than leaving the pane blank.\ncore-start-failed = The document viewer could not be started. Please reload the page.\n";
46359
46359
  const content = '# Worker-generated content: style descriptions ("thick red line"), boolean\n# words, and other prose the core computes into the document. Selected by\n# `documentLocale`, which follows the content\'s language rather than the\n# reader\'s UI language.\n#\n# Message ids are lower-kebab-case Fluent identifiers, optionally with a\n# single `.attribute` suffix (`color.blue`, `noun.line-segment`).\n\n\n## Style vocabulary\n##\n## The words the style pipeline derives from a component\'s numeric and\n## enumerated style values. A word an author writes directly — `lineColorWord`,\n## `markerStyleWord`, and their siblings — passes through untranslated: the\n## author chose those words, and rewriting them would be a surprise. So does a\n## CSS named color asked for by name ("rebeccapurple"), which\n## `resolveColorWord` deliberately preserves.\n##\n## Every adjective here is handed `$gender`, the grammatical gender of the noun\n## it describes (see `noun-gender`). English has no agreement and ignores it; a\n## language that inflects selects on it.\n\n# The canonical color families a color value resolves to.\ncolor =\n .black = black\n .white = white\n .gray = gray\n .red = red\n .orange = orange\n .yellow = yellow\n .green = green\n .cyan = cyan\n .blue = blue\n .purple = purple\n .pink = pink\n .brown = brown\n\n# Stroke widths. Only the extremes are named — a middling width is described by\n# its color alone.\nline-width =\n .thick = thick\n .thin = thin\n\n# Dash patterns. A solid stroke is described by its color alone.\nline-style =\n .dashed = dashed\n .dotted = dotted\n\n# Patterns a shape\'s interior can be filled with. A solid fill is described by\n# its color alone.\nfill-style =\n .horizontal = horizontal lines\n .vertical = vertical lines\n .diagonal = diagonal lines\n .backdiagonal = reverse diagonal lines\n .dots = dots\n .diamonds = diamonds\n\n# The things being described. The shapes a point can be drawn as ("square",\n# "cross") are nouns too: a point\'s description names its marker shape rather\n# than always saying "point".\nnoun =\n .line = line\n .line-segment = line segment\n .ray = ray\n .vector = vector\n .curve = curve\n .function = function\n .parabola = parabola\n .polyline = polyline\n .polygon = polygon\n .triangle = triangle\n .rectangle = rectangle\n .circle = circle\n .region = region\n .point = point\n .square = square\n .diamond = diamond\n .cross = cross\n .plus = plus\n\n# A regular polygon names its side count, so it is a message of its own rather\n# than one of `noun`\'s attributes.\n#\n# `$part` splits the noun where a language needs it split: `head` is the word\n# the adjectives attach to, `tail` a complement that follows them. English\n# folds the side count into the head and has no tail; Spanish says "polígono\n# regular" and puts "de 5 lados" after the adjectives, so that they stay beside\n# the noun they agree with. `style-with-noun` and `style-filled-with-noun`\n# place the two halves.\n#\n# `$numSides` is a real number, so it is formatted by the locale\'s own rules —\n# a 1000-gon reads "1,000-sided" here and "de 1000 lados" in Spanish. That is\n# the number-formatting policy in the README, and the one place a description\n# is not character-for-character what the pre-catalog code produced.\nnoun-regular-polygon =\n { $part ->\n [tail] { "" }\n *[head] { $numSides }-sided regular polygon\n }\n\n# The grammatical gender of the noun being described, passed to every adjective\n# describing it so that translations can agree. English has no grammatical\n# gender, so every noun answers the same and the answer goes unused.\n#\n# `$noun` is one of `noun`\'s attribute names, `regular-polygon` for the shape\n# `noun-regular-polygon` names, or the head of a phrase the description builds\n# without naming it as a noun: `border`, `fill`, `text`, or `background`. A\n# word this message does not list falls to its default gender — which is also\n# what an author\'s own `markerStyleWord` gets, since the catalog has never seen\n# it.\nnoun-gender = neuter\n\n\n## Style composition\n##\n## `$parts` names which pieces the style actually supplies, so that a\n## translation can order and inflect each combination on its own terms instead\n## of substituting into a fixed English frame. An absent piece is a different\n## branch, never an empty placeable.\n\n# The adjectives describing a stroke: its width, its dash pattern, and its\n# color. Also describes a shape\'s border, where the color is dropped when it\n# matches the fill it surrounds.\nstyle-stroke =\n { $parts ->\n [width-style-color] { $width } { $lineStyle } { $color }\n [width-color] { $width } { $color }\n [style-color] { $lineStyle } { $color }\n [width-style] { $width } { $lineStyle }\n [width] { $width }\n [style] { $lineStyle }\n *[color] { $color }\n }\n\n# A style description followed by what it describes: "thick red line".\n#\n# `$nounTail` is the noun\'s trailing complement, for the nouns whose\n# translation splits around the adjectives (see `noun-regular-polygon`).\n# English has none today, so it only ever selects `noun` for itself — the other\n# variant is still what a partly-translated locale falls back to, and dropping\n# it would drop that locale\'s side count.\nstyle-with-noun =\n { $parts ->\n [noun-tail] { $description } { $noun } { $nounTail }\n *[noun] { $description } { $noun }\n }\n\n# The word marking a shape as filled.\n#\n# A key of its own, looked up by the code and handed to the messages below as\n# `$filled`, rather than literal text inside them: a language that inflects it\n# has to agree it with the shape. Referencing it from those messages would not\n# do — a term reference (`{ -filled }`) gets an empty scope and never sees\n# `$gender`, and a message reference resolves only inside its own bundle, so a\n# locale that translated `style-filled` but not this word would render the\n# reference literally instead of falling back to English.\nstyle-filled-word = filled\n\n# A filled shape, and the pattern its interior is drawn with, if any.\nstyle-filled =\n { $parts ->\n [pattern] { $filled } { $color } with { $pattern }\n *[plain] { $filled } { $color }\n }\n\n# The same, naming the shape: "filled blue circle with diamonds".\n#\n# The `-tail` variants carry the noun\'s trailing complement, as\n# `style-with-noun` does.\nstyle-filled-with-noun =\n { $parts ->\n [pattern] { $filled } { $color } { $noun } with { $pattern }\n [plain-tail] { $filled } { $color } { $noun } { $nounTail }\n [pattern-tail] { $filled } { $color } { $noun } { $nounTail } with { $pattern }\n *[plain] { $filled } { $color } { $noun }\n }\n\n# The border clause appended to a filled shape: "with a thick red border".\n#\n# `$parts` carries two distinctions English cares about: whether a fill pattern\n# was already mentioned, which makes this a further clause ("and") rather than\n# the first ("with"), and whether the surrounding description named the shape,\n# which is where English wants an article.\nstyle-border-clause =\n { $parts ->\n [with-article] with a { $border } border\n [and] and { $border } border\n [and-article] and a { $border } border\n *[with] with { $border } border\n }\n\n# How a shape\'s interior is filled, on its own: "blue diamonds".\nstyle-fill =\n { $parts ->\n [pattern] { $color } { $pattern }\n *[plain] { $color }\n }\n\nstyle-unfilled = unfilled\n\n# How a piece of text is styled: its color, and the background behind it.\nstyle-text =\n { $parts ->\n [background] { $color } with a { $background } background\n *[plain] { $color }\n }\n\n# What `backgroundColor` answers when nothing is drawn behind the text.\nstyle-background-none = none\n';
46360
- const diagnostics = '# Errors and warnings surfaced to the reader or author. Produced by the worker\n# but addressed to whoever is looking at the screen, so these are selected by\n# `uiLocale`, not `documentLocale`.\n#\n# Message ids are lower-kebab-case Fluent identifiers, optionally with a\n# single `.attribute` suffix (`invalid-attribute-value`).\n#\n# Reached by stable diagnostic code rather than by a literal `t("key")` call:\n# `DIAGNOSTIC_CODES` in `src/diagnostics.ts` maps `doenet-w0001` to the id\n# below, and `lint:i18n` treats that registry as the call site. Adding a\n# message here without registering a code for it fails the lint as an orphan.\n#\n# Translators: `through`, `endpoint`, `midpointOffset`, `numDimensions` and the\n# like are DoenetML attribute names. They are part of the language, not prose,\n# and must be left in English exactly as written.\n\n## `<lineSegment>`\n\n# $attributes is a list of attribute names; $attributesCount is its length.\nline-segment-attributes-ignored-with-endpoints =\n { $attributesCount ->\n [one] { $attributes } is ignored when two endpoints are specified\n *[other] { $attributes } are ignored when two endpoints are specified\n }\n\n# $attributes is a list of attribute names; $attributesCount is its length.\nline-segment-attributes-ignored-with-endpoint-and-midpoint =\n { $attributesCount ->\n [one] { $attributes } is ignored when an endpoint and a midpoint are both specified\n *[other] { $attributes } are ignored when an endpoint and a midpoint are both specified\n }\n\nline-segment-midpoint-offset-without-midpoint = midpointOffset has no effect without a midpoint\n\n## `<line>`\n\nline-points-undetermined-dimensions = Line through points of undetermined dimensions.\n\nline-points-too-few-dimensions = Line must be through points of at least two dimensions.\n\n# $variables is a bare enumeration of variable names, not an "and" list.\nline-points-depend-on-variables = Line is through points that depend on variables: { $variables }.\n\nline-equation-invalid-format = Invalid format for equation of line in variables { $variable1 } and { $variable2 }.\n\n## `<ray>`\n\nray-overprescribed-through = Ray is prescribed by through, endpoint, and direction. Ignoring specified through.\n\nray-dimension-mismatch = numDimensions mismatch in ray.\n\n## `<vector>`\n\nvector-overprescribed-head = Vector is prescribed by head, tail, and displacement. Ignoring specified head.\n\nvector-dimension-mismatch = numDimensions mismatch in vector.\n';
46360
+ const diagnostics = '# Errors and warnings surfaced to the reader or author. Produced by the worker\n# but addressed to whoever is looking at the screen, so these are selected by\n# `uiLocale`, not `documentLocale`.\n#\n# Message ids are lower-kebab-case Fluent identifiers, optionally with a\n# single `.attribute` suffix (`invalid-attribute-value`).\n#\n# Reached by stable diagnostic code rather than by a literal `t("key")` call:\n# `DIAGNOSTIC_CODES` in `src/diagnostics.ts` maps `doenet-w0001` to the id\n# below, and `lint:i18n` treats that registry as the call site. Adding a\n# message here without registering a code for it fails the lint as an orphan.\n#\n# Translators: `through`, `endpoint`, `midpointOffset`, `numDimensions` and the\n# like are DoenetML attribute names. They are part of the language, not prose,\n# and must be left in English exactly as written.\n\n## `<lineSegment>`\n\n# $attributes is a list of attribute names; $attributesCount is its length.\nline-segment-attributes-ignored-with-endpoints =\n { $attributesCount ->\n [one] { $attributes } is ignored when two endpoints are specified\n *[other] { $attributes } are ignored when two endpoints are specified\n }\n\n# $attributes is a list of attribute names; $attributesCount is its length.\nline-segment-attributes-ignored-with-endpoint-and-midpoint =\n { $attributesCount ->\n [one] { $attributes } is ignored when an endpoint and a midpoint are both specified\n *[other] { $attributes } are ignored when an endpoint and a midpoint are both specified\n }\n\nline-segment-midpoint-offset-without-midpoint = midpointOffset has no effect without a midpoint\n\n## `<line>`\n\nline-points-undetermined-dimensions = Line through points of undetermined dimensions.\n\nline-points-too-few-dimensions = Line must be through points of at least two dimensions.\n\n# $variables is a bare enumeration of variable names, not an "and" list.\nline-points-depend-on-variables = Line is through points that depend on variables: { $variables }.\n\nline-equation-invalid-format = Invalid format for equation of line in variables { $variable1 } and { $variable2 }.\n\n## `<ray>`\n\nray-overprescribed-through = Ray is prescribed by through, endpoint, and direction. Ignoring specified through.\n\nray-dimension-mismatch = numDimensions mismatch in ray.\n\n## `<vector>`\n\nvector-overprescribed-head = Vector is prescribed by head, tail, and displacement. Ignoring specified head.\n\nvector-dimension-mismatch = numDimensions mismatch in vector.\n\n## Attracting and constraining\n\n# $component is the DoenetML tag of the child that was named, e.g. "polygon".\nattract-to-without-nearest-point = Cannot attract to a `<{ $component }>` as it doesn\'t have a nearestPoint state variable.\n\nconstrain-to-without-nearest-point = Cannot constrain to a `<{ $component }>` as it doesn\'t have a nearestPoint state variable.\n\nconstrain-to-interior-without-nearest-point = Cannot constrain to interior of a `<{ $component }>` as it doesn\'t have a nearestPoint state variable.\n\n## `<choiceInput>`\n\n# Translators: `labelPosition` is an attribute name and stays in English.\nchoice-input-label-position-ignored = labelPosition is ignored for non-inline choiceInput\n\n## Ordering children by index\n##\n## These name the component in prose rather than as a tag, matching how the\n## messages have always read. The component names stay in English; the nouns\n## around them are prose and should be translated.\n\nchoice-input-indices-count-mismatch = Ignoring indices specified for choiceInput as number of indices doesn\'t match number of choice children.\n\npretzel-indices-count-mismatch = Ignoring indices specified for problem as number of indices doesn\'t match number of problem children.\n\nshuffle-indices-count-mismatch = Ignoring indices specified for shuffle as number of indices doesn\'t match number of components.\n\n# $component is `choiceInput`, `pretzel` or `shuffle` — a DoenetML component\n# name, so it stays in English.\nindices-ignored-out-of-range = Ignoring indices specified for { $component } as some indices out of range.\n\npretzel-indices-repeated = Ignoring indices specified for pretzel as some indices are repeated.\n\npretzel-circuit-first-index = Ignoring indices specified for pretzel in circuit mode as the first index must be 1.\n\n## `<shuffle>` and `<sort>`\n\n# $component is `shuffle` or `sort`. These two components accept the same\n# children and fail the same ways, so they share their messages.\nstring-children-need-type = For `<{ $component }>` to work with string children, a `type` attribute must be specified.\n\n# $type is what the author wrote; math, text, number and boolean are attribute\n# values and stay in English.\ninvalid-type-defaulting-to-math = Invalid type { $type } for { $component } component. Must be one of math, text, number, or boolean. Defaulting to math.\n\n# $value is the string child that could not be used.\nstring-not-valid-component-to-arrange = String "{ $value }" is not a valid component to { $component }. Ignoring.\n\n## Types and variables\n\ninvalid-type-defaulting-to-number = Invalid type { $type }, setting type to number.\n\ninvalid-variable-value = Invalid value of a variable: `{ $value }`\n\n## Variants\n\n# $index is what the author wrote, reproduced verbatim rather than as a number:\n# it reached this message precisely because it was not one.\nvariant-index-must-be-number = Variant index { $index } must be a number\n\nvariant-index-must-be-integer = Variant index { $index } must be an integer\n\n## `<sideBySide>`\n\n# $component is `sideBySide` or `sbsGroup`.\nside-by-side-absolute-widths = `<{ $component }>` is not implemented for absolute measurements. Setting widths to relative.\n\nside-by-side-absolute-margins = `<{ $component }>` is not implemented for absolute measurements. Setting margins to relative.\n\nside-by-side-no-block-child = Invalid `<{ $component }>`: it must have at least one block child.\n\n## `<label>`\n\n# Translators: `for` is an attribute name and stays in English.\nlabel-for-ignored-on-graphical = The `for` attribute on graphical `<label>` is ignored.\n\nlabel-for-must-resolve-to-one = The `for` attribute on `<label>` must resolve to exactly one component.\n\nlabel-for-unresolved = The `for` attribute on `<label>` could not be resolved to a component.\n\nlabel-for-answer-with-authored-inputs = The `for` attribute on `<label>` references an `<answer>` with explicitly authored inputs; reference the input directly.\n\nlabel-for-answer-without-input = The `for` attribute on `<label>` references an `<answer>` without an input to label.\n\nlabel-for-must-reference-input-or-answer = The `for` attribute on `<label>` must reference an input or an answer.\n\n## Accessibility\n\n# $component is a DoenetML tag, e.g. "graph" or "image".\naccessibility-short-description-or-decorative = For accessibility, `<{ $component }>` must either have a short description or be specified as decorative.\n\naccessibility-video-short-description = For accessibility, `<video>` must have a short description.\n\naccessibility-input-short-description-or-label = For accessibility, `<{ $component }>` must have a short description or a label.\n\n# The companion to the message above, for the input an `<answer>` creates on the\n# author\'s behalf. Two messages rather than one with the subject passed in: the\n# subject is a phrase here, not a name, and a phrase handed over as an argument\n# would never reach a translator.\naccessibility-answer-input-short-description-or-label = For accessibility, an `<answer>` creating an input must have a short description or a label.\n\naccessibility-short-description-contains-math = Short descriptions should not contain math components such as `<{ $component }>`. Spell out any math with words.\n\n# $colorName is an attribute name and stays in English. $ratio and $threshold\n# are contrast ratios; $mode says which theme the shortfall was measured in,\n# and is `dark` or `light`.\naccessibility-section-title-insufficient-contrast =\n { $mode ->\n [dark] { $colorName } has insufficient contrast for the section heading text (dark mode) ({ NUMBER($ratio, minimumFractionDigits: 2, maximumFractionDigits: 2) }:1; requires at least { $threshold }:1).\n *[other] { $colorName } has insufficient contrast for the section heading text ({ NUMBER($ratio, minimumFractionDigits: 2, maximumFractionDigits: 2) }:1; requires at least { $threshold }:1).\n }\n';
46361
46361
  const editor = "# Editor and language-server surfaces: formatter labels, completion detail\n# text, hover help. Selected by `uiLocale`.\n#\n# Intentionally empty in i18n Phase 0 (#1515). A later phase moves the editor\n# strings into this file; note that the LSP ships bundled with its DoenetML\n# version, so these catalogs are version-correct rather than always-latest.\n#\n# Message ids are lower-kebab-case Fluent identifiers, optionally with a\n# single `.attribute` suffix (`format-document`).\n";
46362
46362
  const CATALOG_NAMESPACES = [
46363
46363
  "chrome",
@@ -46717,7 +46717,7 @@ function normalizeLocaleTag(tag2) {
46717
46717
  }
46718
46718
  const esChrome = "# Spanish viewer chrome. Translated from `locales/en/chrome.ftl`, which is the\n# source of truth: `lint:i18n` rejects a key that does not exist there, and\n# reports a key that exists there but not here as missing coverage.\n#\n# Message ids are never translated — only the text to the right of `=`.\n#\n# Register: impersonal throughout — infinitives and bare nouns, never a `tú`\n# or `usted` verb form. The viewer does not know how formally a deployment\n# addresses its readers, and an impersonal label is correct for both.\n\n\n## Answer submission\n\nanswer-checking = Comprobando...\nanswer-submitting = Enviando...\n\nanswer-checking-status = Comprobando la respuesta\nanswer-submitting-status = Enviando la respuesta\n\nanswer-correct = Correcto\nanswer-incorrect = Incorrecto\n\nanswer-response-saved = Respuesta guardada\n\n# Spanish typographic convention puts a space before the percent sign.\nanswer-percent-credit = { $percent } % de crédito\nanswer-percent-correct = { $percent } % correcto\nanswer-percent-short = { $percent } %\n\nmax-credit-available = Crédito máximo disponible: { $percent } %\n\nattempts-remaining =\n { $count ->\n [0] no quedan intentos\n [one] queda { $count } intento\n *[other] quedan { $count } intentos\n }\n\nvalidation-correct = (Correcto)\nvalidation-incorrect = (Incorrecto)\nvalidation-partially-correct = (Parcialmente correcto)\n\n# `Mostrar` is the infinitive, per the register note above.\nanswer-show-responses =\n { $count ->\n [one] Mostrar { $count } respuesta a { $answerId }\n *[other] Mostrar { $count } respuestas a { $answerId }\n }\n\n\n## Disclosure panels\n\nfeedback-heading = Comentarios\n\ncollapsible-click-to-open = (clic para abrir)\ncollapsible-click-to-close = (clic para cerrar)\ncollapsible-initializing = Inicializando...\n\nfootnote-show = Mostrar la nota al pie\nfootnote-hide = Ocultar la nota al pie\n\ndescription-more-information = más información\n\n\n## Controls\n\nslider-previous = Anterior\nslider-next = Siguiente\n\nkeyboard-open = Abrir el teclado\nkeyboard-close = Cerrar el teclado\n\nmatrix-remove-row = Eliminar fila\nmatrix-add-row = Añadir fila\nmatrix-remove-column = Eliminar columna\nmatrix-add-column = Añadir columna\n\nsubset-add-remove-points = Añadir/Eliminar puntos\nsubset-toggle-points-intervals = Alternar puntos e intervalos\nsubset-move-points = Mover puntos\nsubset-clear = Borrar\n\norbital-add-row = Añadir fila\norbital-remove-row = Eliminar fila\norbital-add-box = Añadir casilla\norbital-remove-box = Eliminar casilla\norbital-add-up-arrow = Añadir flecha hacia arriba\norbital-add-down-arrow = Añadir flecha hacia abajo\norbital-remove-arrow = Eliminar flecha\n\norbital-row-label = Etiqueta de la fila { $row }\n\npretzel-answer = Respuesta\n\nsummary-statistics-caption = Resumen estadístico de { $column }\n\n\n## Math input\n\nmath-input-preview-region = vista previa de la expresión matemática\nmath-input-preview = Vista previa\nmath-input-invalid-expression = Expresión no válida:\n\n\n## Document status\n\nviewer-initializing = Inicializando...\n\n\n## Errors\n\nerror-heading = Error\n\ndocument-contains-errors = ¡Este documento contiene errores!\n\nsomething-went-wrong = Algo salió mal.\n\n# Follows `error-heading` and a colon, so it begins in lower case, as in\n# English. The instruction is an infinitive, per the register note above.\nrenderer-load-failed = no se pudo cargar un componente. Recargar la página.\n\ncore-start-failed = No se pudo iniciar el visor del documento. Recargar la página.\n";
46719
46719
  const esContent = "# Spanish content catalog: the prose the core computes into the document.\n# Selected by `documentLocale` — the language the activity was written in.\n#\n# Spanish inflects. Adjectives follow their noun and agree with it in gender,\n# so every adjective below selects on `$gender`, the gender of the noun it\n# describes, and the composition messages put the noun first. Neither is\n# expressible by substituting into the English word order, which is why the\n# catalog controls the order and not the code.\n\n\n## Vocabulario de estilos\n\ncolor =\n .black =\n { $gender ->\n [f] negra\n *[m] negro\n }\n .white =\n { $gender ->\n [f] blanca\n *[m] blanco\n }\n .gray = gris\n .red =\n { $gender ->\n [f] roja\n *[m] rojo\n }\n .orange = naranja\n .yellow =\n { $gender ->\n [f] amarilla\n *[m] amarillo\n }\n .green = verde\n .cyan = cian\n .blue = azul\n .purple =\n { $gender ->\n [f] morada\n *[m] morado\n }\n .pink = rosa\n .brown = marrón\n\nline-width =\n .thick =\n { $gender ->\n [f] gruesa\n *[m] grueso\n }\n .thin =\n { $gender ->\n [f] delgada\n *[m] delgado\n }\n\nline-style =\n .dashed =\n { $gender ->\n [f] discontinua\n *[m] discontinuo\n }\n .dotted =\n { $gender ->\n [f] punteada\n *[m] punteado\n }\n\n# Sintagmas nominales: van detrás de «con» y no concuerdan con nada.\nfill-style =\n .horizontal = líneas horizontales\n .vertical = líneas verticales\n .diagonal = líneas diagonales\n .backdiagonal = líneas diagonales inversas\n .dots = puntos\n .diamonds = rombos\n\nnoun =\n .line = línea\n .line-segment = segmento\n .ray = semirrecta\n .vector = vector\n .curve = curva\n .function = función\n .parabola = parábola\n .polyline = polilínea\n .polygon = polígono\n .triangle = triángulo\n .rectangle = rectángulo\n .circle = círculo\n .region = región\n .point = punto\n .square = cuadrado\n .diamond = rombo\n .cross = cruz\n .plus = signo más\n\n# El nombre se parte: «polígono regular» lleva los adjetivos y «de 5 lados»\n# cierra el sintagma detrás de ellos. Si el complemento fuera delante, los\n# adjetivos quedarían separados del nombre con el que concuerdan («polígono\n# regular de 5 lados grueso rojo»).\nnoun-regular-polygon =\n { $part ->\n [tail] de { $numSides } lados\n *[head] polígono regular\n }\n\n# Además de los nombres de arriba, `$noun` puede ser «regular-polygon» (el\n# nombre que compone `noun-regular-polygon`) o el núcleo de un sintagma que no\n# se nombra en la descripción: «border», «fill», «text» y «background». Todos\n# ellos son masculinos en español —polígono, borde, relleno, texto, fondo—, así\n# que caen en el caso por defecto.\nnoun-gender =\n { $noun ->\n [line] f\n [ray] f\n [curve] f\n [function] f\n [parabola] f\n [polyline] f\n [region] f\n [cross] f\n *[other] m\n }\n\n\n## Composición de estilos\n\nstyle-stroke =\n { $parts ->\n [width-style-color] { $lineStyle } { $width } { $color }\n [width-color] { $width } { $color }\n [style-color] { $lineStyle } { $color }\n [width-style] { $lineStyle } { $width }\n [width] { $width }\n [style] { $lineStyle }\n *[color] { $color }\n }\n\n# El nombre va delante y los adjetivos detrás: «línea discontinua gruesa roja».\n# El complemento del nombre, si lo hay, cierra el sintagma: «polígono regular\n# grueso rojo de 5 lados».\nstyle-with-noun =\n { $parts ->\n [noun-tail] { $noun } { $description } { $nounTail }\n *[noun] { $noun } { $description }\n }\n\nstyle-filled-word =\n { $gender ->\n [f] rellena\n *[m] relleno\n }\n\nstyle-filled =\n { $parts ->\n [pattern] { $color } { $filled } con { $pattern }\n *[plain] { $color } { $filled }\n }\n\n# Aquí el complemento va pegado al nombre, y no al final como en\n# `style-with-noun`: «relleno de …» se lee como «lleno de …», así que «relleno\n# de 5 lados» diría otra cosa. «Polígono regular de 5 lados azul relleno».\nstyle-filled-with-noun =\n { $parts ->\n [pattern] { $noun } { $color } { $filled } con { $pattern }\n [plain-tail] { $noun } { $nounTail } { $color } { $filled }\n [pattern-tail] { $noun } { $nounTail } { $color } { $filled } con { $pattern }\n *[plain] { $noun } { $color } { $filled }\n }\n\n# «borde» es masculino, así que los adjetivos del borde concuerdan con él y no\n# con la figura que rodea.\nstyle-border-clause =\n { $parts ->\n [with-article] con un borde { $border }\n [and] y borde { $border }\n [and-article] y un borde { $border }\n *[with] con borde { $border }\n }\n\n# «de color» evita tener que concordar el color con un patrón en plural.\nstyle-fill =\n { $parts ->\n [pattern] { $pattern } de color { $color }\n *[plain] { $color }\n }\n\nstyle-unfilled = sin relleno\n\nstyle-text =\n { $parts ->\n [background] { $color } con un fondo { $background }\n *[plain] { $color }\n }\n\nstyle-background-none = ninguno\n";
46720
- const esDiagnostics = "# Advertencias y errores mostrados a quien lee o escribe el documento.\n# Seleccionados por `uiLocale`.\n#\n# Los nombres de atributos y componentes de DoenetML (`through`, `endpoint`,\n# `numDimensions`, …) forman parte del lenguaje y se dejan en inglés.\n\n## `<lineSegment>`\n\nline-segment-attributes-ignored-with-endpoints =\n { $attributesCount ->\n [one] { $attributes } se ignora cuando se especifican los dos extremos\n *[other] { $attributes } se ignoran cuando se especifican los dos extremos\n }\n\nline-segment-attributes-ignored-with-endpoint-and-midpoint =\n { $attributesCount ->\n [one] { $attributes } se ignora cuando se especifican un extremo y el punto medio\n *[other] { $attributes } se ignoran cuando se especifican un extremo y el punto medio\n }\n\nline-segment-midpoint-offset-without-midpoint = midpointOffset no tiene efecto sin un punto medio\n\n## `<line>`\n\n# «Recta», no «línea», aunque `noun.line` en content.ftl diga «línea»: no es\n# una incoherencia, sino la diferencia entre describir el trazo dibujado («una\n# línea azul gruesa») y hablar del objeto geométrico, que en matemáticas es\n# una recta —de ahí «la ecuación de la recta».\n\nline-points-undetermined-dimensions = La recta pasa por puntos de dimensiones indeterminadas.\n\nline-points-too-few-dimensions = La recta debe pasar por puntos de al menos dos dimensiones.\n\nline-points-depend-on-variables = La recta pasa por puntos que dependen de las variables: { $variables }.\n\n# Enumeradas con coma en vez de «y»: las variables de <line> son `x` e `y` por\n# omisión, y «en las variables x y y» sería a la vez incorrecto (ante el sonido\n# /i/ la conjunción es «e») e ilegible. La coma es correcta sea cual sea el\n# nombre de la variable, que aquí no se conoce de antemano.\nline-equation-invalid-format = Formato no válido para la ecuación de la recta en las variables { $variable1 }, { $variable2 }.\n\n## `<ray>`\n\nray-overprescribed-through = La semirrecta está determinada por through, endpoint y direction. Se ignora el through especificado.\n\nray-dimension-mismatch = Discrepancia de numDimensions en la semirrecta.\n\n## `<vector>`\n\nvector-overprescribed-head = El vector está determinado por head, tail y displacement. Se ignora el head especificado.\n\nvector-dimension-mismatch = Discrepancia de numDimensions en el vector.\n";
46720
+ const esDiagnostics = '# Advertencias y errores mostrados a quien lee o escribe el documento.\n# Seleccionados por `uiLocale`.\n#\n# Los nombres de atributos y componentes de DoenetML (`through`, `endpoint`,\n# `numDimensions`, …) forman parte del lenguaje y se dejan en inglés.\n\n## `<lineSegment>`\n\nline-segment-attributes-ignored-with-endpoints =\n { $attributesCount ->\n [one] { $attributes } se ignora cuando se especifican los dos extremos\n *[other] { $attributes } se ignoran cuando se especifican los dos extremos\n }\n\nline-segment-attributes-ignored-with-endpoint-and-midpoint =\n { $attributesCount ->\n [one] { $attributes } se ignora cuando se especifican un extremo y el punto medio\n *[other] { $attributes } se ignoran cuando se especifican un extremo y el punto medio\n }\n\nline-segment-midpoint-offset-without-midpoint = midpointOffset no tiene efecto sin un punto medio\n\n## `<line>`\n\n# «Recta», no «línea», aunque `noun.line` en content.ftl diga «línea»: no es\n# una incoherencia, sino la diferencia entre describir el trazo dibujado («una\n# línea azul gruesa») y hablar del objeto geométrico, que en matemáticas es\n# una recta —de ahí «la ecuación de la recta».\n\nline-points-undetermined-dimensions = La recta pasa por puntos de dimensiones indeterminadas.\n\nline-points-too-few-dimensions = La recta debe pasar por puntos de al menos dos dimensiones.\n\nline-points-depend-on-variables = La recta pasa por puntos que dependen de las variables: { $variables }.\n\n# Enumeradas con coma en vez de «y»: las variables de <line> son `x` e `y` por\n# omisión, y «en las variables x y y» sería a la vez incorrecto (ante el sonido\n# /i/ la conjunción es «e») e ilegible. La coma es correcta sea cual sea el\n# nombre de la variable, que aquí no se conoce de antemano.\nline-equation-invalid-format = Formato no válido para la ecuación de la recta en las variables { $variable1 }, { $variable2 }.\n\n## `<ray>`\n\nray-overprescribed-through = La semirrecta está determinada por through, endpoint y direction. Se ignora el through especificado.\n\nray-dimension-mismatch = Discrepancia de numDimensions en la semirrecta.\n\n## `<vector>`\n\nvector-overprescribed-head = El vector está determinado por head, tail y displacement. Se ignora el head especificado.\n\nvector-dimension-mismatch = Discrepancia de numDimensions en el vector.\n\n## Atraer y restringir\n\nattract-to-without-nearest-point = No se puede atraer a un `<{ $component }>` porque no tiene la variable de estado nearestPoint.\n\nconstrain-to-without-nearest-point = No se puede restringir a un `<{ $component }>` porque no tiene la variable de estado nearestPoint.\n\nconstrain-to-interior-without-nearest-point = No se puede restringir al interior de un `<{ $component }>` porque no tiene la variable de estado nearestPoint.\n\n## `<choiceInput>`\n\nchoice-input-label-position-ignored = labelPosition se ignora en un choiceInput que no es inline\n\n## Ordenar hijos por índice\n\nchoice-input-indices-count-mismatch = Se ignoran los índices especificados para choiceInput porque su cantidad no coincide con la cantidad de hijos choice.\n\npretzel-indices-count-mismatch = Se ignoran los índices especificados para problem porque su cantidad no coincide con la cantidad de hijos problem.\n\nshuffle-indices-count-mismatch = Se ignoran los índices especificados para shuffle porque su cantidad no coincide con la cantidad de componentes.\n\nindices-ignored-out-of-range = Se ignoran los índices especificados para { $component } porque algunos están fuera de rango.\n\npretzel-indices-repeated = Se ignoran los índices especificados para pretzel porque algunos están repetidos.\n\npretzel-circuit-first-index = Se ignoran los índices especificados para pretzel en modo circuit porque el primer índice debe ser 1.\n\n## `<shuffle>` y `<sort>`\n\nstring-children-need-type = Para que `<{ $component }>` funcione con hijos de texto, se debe especificar el atributo `type`.\n\ninvalid-type-defaulting-to-math = Tipo no válido { $type } para el componente { $component }. Debe ser math, text, number o boolean. Se usa math.\n\nstring-not-valid-component-to-arrange = La cadena "{ $value }" no es un componente válido para { $component }. Se ignora.\n\n## Tipos y variables\n\ninvalid-type-defaulting-to-number = Tipo no válido { $type }, se establece el tipo en number.\n\ninvalid-variable-value = Valor no válido de una variable: `{ $value }`\n\n## Variantes\n\nvariant-index-must-be-number = El índice de variante { $index } debe ser un número\n\nvariant-index-must-be-integer = El índice de variante { $index } debe ser un número entero\n\n## `<sideBySide>`\n\nside-by-side-absolute-widths = `<{ $component }>` no está implementado para medidas absolutas. Los anchos se establecen como relativos.\n\nside-by-side-absolute-margins = `<{ $component }>` no está implementado para medidas absolutas. Los márgenes se establecen como relativos.\n\nside-by-side-no-block-child = `<{ $component }>` no es válido: debe tener al menos un hijo de bloque.\n\n## `<label>`\n\nlabel-for-ignored-on-graphical = Se ignora el atributo `for` en un `<label>` gráfico.\n\nlabel-for-must-resolve-to-one = El atributo `for` de `<label>` debe corresponder exactamente a un componente.\n\nlabel-for-unresolved = No se pudo resolver el atributo `for` de `<label>` a un componente.\n\nlabel-for-answer-with-authored-inputs = El atributo `for` de `<label>` hace referencia a un `<answer>` con entradas escritas explícitamente; haz referencia a la entrada directamente.\n\nlabel-for-answer-without-input = El atributo `for` de `<label>` hace referencia a un `<answer>` que no tiene ninguna entrada que etiquetar.\n\nlabel-for-must-reference-input-or-answer = El atributo `for` de `<label>` debe hacer referencia a una entrada o a un `<answer>`.\n\n## Accesibilidad\n\naccessibility-short-description-or-decorative = Por accesibilidad, `<{ $component }>` debe tener una descripción breve o estar marcado como decorativo.\n\naccessibility-video-short-description = Por accesibilidad, `<video>` debe tener una descripción breve.\n\naccessibility-input-short-description-or-label = Por accesibilidad, `<{ $component }>` debe tener una descripción breve o una etiqueta.\n\naccessibility-answer-input-short-description-or-label = Por accesibilidad, la entrada creada por un `<answer>` debe tener una descripción breve o una etiqueta.\n\naccessibility-short-description-contains-math = Las descripciones breves no deben contener componentes matemáticos como `<{ $component }>`. Expresa las matemáticas con palabras.\n\naccessibility-section-title-insufficient-contrast =\n { $mode ->\n [dark] { $colorName } no tiene suficiente contraste con el texto del encabezado de sección (modo oscuro) ({ NUMBER($ratio, minimumFractionDigits: 2, maximumFractionDigits: 2) }:1; se requiere al menos { $threshold }:1).\n *[other] { $colorName } no tiene suficiente contraste con el texto del encabezado de sección ({ NUMBER($ratio, minimumFractionDigits: 2, maximumFractionDigits: 2) }:1; se requiere al menos { $threshold }:1).\n }\n';
46721
46721
  const BUNDLED_TRANSLATIONS = {
46722
46722
  es: {
46723
46723
  chrome: esChrome,
@@ -46763,6 +46763,14 @@ const DIAGNOSTIC_CODES = {
46763
46763
  "doenet-i0001": "line-segment-attributes-ignored-with-endpoints",
46764
46764
  "doenet-i0002": "line-segment-midpoint-offset-without-midpoint",
46765
46765
  "doenet-i0003": "line-segment-attributes-ignored-with-endpoint-and-midpoint",
46766
+ "doenet-i0004": "choice-input-indices-count-mismatch",
46767
+ "doenet-i0005": "pretzel-indices-count-mismatch",
46768
+ "doenet-i0006": "shuffle-indices-count-mismatch",
46769
+ "doenet-i0007": "indices-ignored-out-of-range",
46770
+ "doenet-i0008": "pretzel-indices-repeated",
46771
+ "doenet-i0009": "pretzel-circuit-first-index",
46772
+ "doenet-i0010": "variant-index-must-be-number",
46773
+ "doenet-i0011": "variant-index-must-be-integer",
46766
46774
  "doenet-w0001": "line-points-undetermined-dimensions",
46767
46775
  "doenet-w0002": "line-points-too-few-dimensions",
46768
46776
  "doenet-w0003": "line-points-depend-on-variables",
@@ -46770,7 +46778,31 @@ const DIAGNOSTIC_CODES = {
46770
46778
  "doenet-w0005": "ray-overprescribed-through",
46771
46779
  "doenet-w0006": "ray-dimension-mismatch",
46772
46780
  "doenet-w0007": "vector-overprescribed-head",
46773
- "doenet-w0008": "vector-dimension-mismatch"
46781
+ "doenet-w0008": "vector-dimension-mismatch",
46782
+ "doenet-w0009": "attract-to-without-nearest-point",
46783
+ "doenet-w0010": "constrain-to-without-nearest-point",
46784
+ "doenet-w0011": "constrain-to-interior-without-nearest-point",
46785
+ "doenet-w0012": "choice-input-label-position-ignored",
46786
+ "doenet-w0013": "string-children-need-type",
46787
+ "doenet-w0014": "invalid-type-defaulting-to-math",
46788
+ "doenet-w0015": "string-not-valid-component-to-arrange",
46789
+ "doenet-w0016": "invalid-type-defaulting-to-number",
46790
+ "doenet-w0017": "invalid-variable-value",
46791
+ "doenet-w0018": "side-by-side-absolute-widths",
46792
+ "doenet-w0019": "side-by-side-absolute-margins",
46793
+ "doenet-w0020": "side-by-side-no-block-child",
46794
+ "doenet-w0021": "label-for-ignored-on-graphical",
46795
+ "doenet-w0022": "label-for-must-resolve-to-one",
46796
+ "doenet-w0023": "label-for-unresolved",
46797
+ "doenet-w0024": "label-for-answer-with-authored-inputs",
46798
+ "doenet-w0025": "label-for-answer-without-input",
46799
+ "doenet-w0026": "label-for-must-reference-input-or-answer",
46800
+ "doenet-a0001": "accessibility-short-description-or-decorative",
46801
+ "doenet-a0002": "accessibility-video-short-description",
46802
+ "doenet-a0003": "accessibility-input-short-description-or-label",
46803
+ "doenet-a0004": "accessibility-answer-input-short-description-or-label",
46804
+ "doenet-a0005": "accessibility-short-description-contains-math",
46805
+ "doenet-a0006": "accessibility-section-title-insufficient-contrast"
46774
46806
  };
46775
46807
  function isDiagnosticCode(code) {
46776
46808
  return Object.prototype.hasOwnProperty.call(DIAGNOSTIC_CODES, code);
@@ -77036,6 +77068,24 @@ function exprContainsVector(tree) {
77036
77068
  }
77037
77069
  return operands.some(exprContainsVector);
77038
77070
  }
77071
+ function codedDiagnostic({
77072
+ type,
77073
+ code,
77074
+ args,
77075
+ position: position2,
77076
+ sourceDoc,
77077
+ level
77078
+ }) {
77079
+ return {
77080
+ type,
77081
+ message: formatEnglishDiagnostic(code, args),
77082
+ code,
77083
+ ...args === void 0 ? {} : { args },
77084
+ ...position2 === void 0 ? {} : { position: position2 },
77085
+ ...sourceDoc === void 0 ? {} : { sourceDoc },
77086
+ ...level === void 0 ? {} : { level }
77087
+ };
77088
+ }
77039
77089
  class Label extends InlineComponent {
77040
77090
  constructor(args) {
77041
77091
  super(args);
@@ -77457,20 +77507,26 @@ class Label extends InlineComponent {
77457
77507
  let targetComponentIdx = null;
77458
77508
  if (hasForAttribute) {
77459
77509
  if (isGraphicalLabel) {
77460
- diagnostics2.push({
77461
- message: "The `for` attribute on graphical `<label>` is ignored.",
77462
- type: "warning"
77463
- });
77510
+ diagnostics2.push(
77511
+ codedDiagnostic({
77512
+ type: "warning",
77513
+ code: "doenet-w0021"
77514
+ })
77515
+ );
77464
77516
  } else if (forResolutions.length !== 1) {
77465
- diagnostics2.push({
77466
- message: "The `for` attribute on `<label>` must resolve to exactly one component.",
77467
- type: "warning"
77468
- });
77517
+ diagnostics2.push(
77518
+ codedDiagnostic({
77519
+ type: "warning",
77520
+ code: "doenet-w0022"
77521
+ })
77522
+ );
77469
77523
  } else if (forResolutions[0].unresolvedPath !== null) {
77470
- diagnostics2.push({
77471
- message: "The `for` attribute on `<label>` could not be resolved to a component.",
77472
- type: "warning"
77473
- });
77524
+ diagnostics2.push(
77525
+ codedDiagnostic({
77526
+ type: "warning",
77527
+ code: "doenet-w0023"
77528
+ })
77529
+ );
77474
77530
  } else {
77475
77531
  targetComponentIdx = forResolutions[0].componentIdx;
77476
77532
  }
@@ -77578,28 +77634,34 @@ class Label extends InlineComponent {
77578
77634
  };
77579
77635
  }
77580
77636
  if (answerHasAuthoredInputChildrenForLabel) {
77581
- diagnostics2.push({
77582
- message: "The `for` attribute on `<label>` references an `<answer>` with explicitly authored inputs; reference the input directly.",
77583
- type: "warning"
77584
- });
77637
+ diagnostics2.push(
77638
+ codedDiagnostic({
77639
+ type: "warning",
77640
+ code: "doenet-w0024"
77641
+ })
77642
+ );
77585
77643
  return {
77586
77644
  setValue: { forTargetInputComponentIdx: null },
77587
77645
  sendDiagnostics: diagnostics2
77588
77646
  };
77589
77647
  }
77590
- diagnostics2.push({
77591
- message: "The `for` attribute on `<label>` references an `<answer>` without an input to label.",
77592
- type: "warning"
77593
- });
77648
+ diagnostics2.push(
77649
+ codedDiagnostic({
77650
+ type: "warning",
77651
+ code: "doenet-w0025"
77652
+ })
77653
+ );
77594
77654
  return {
77595
77655
  setValue: { forTargetInputComponentIdx: null },
77596
77656
  sendDiagnostics: diagnostics2
77597
77657
  };
77598
77658
  }
77599
- diagnostics2.push({
77600
- message: "The `for` attribute on `<label>` must reference an input or an answer.",
77601
- type: "warning"
77602
- });
77659
+ diagnostics2.push(
77660
+ codedDiagnostic({
77661
+ type: "warning",
77662
+ code: "doenet-w0026"
77663
+ })
77664
+ );
77603
77665
  return {
77604
77666
  setValue: { forTargetInputComponentIdx: null },
77605
77667
  sendDiagnostics: diagnostics2
@@ -93747,7 +93809,7 @@ function addSectionTitleColorContrastDiagnostic({
93747
93809
  colorName: colorName2,
93748
93810
  textColor,
93749
93811
  canvasColor,
93750
- modeSuffix = ""
93812
+ mode = "light"
93751
93813
  }) {
93752
93814
  if (!authorSet || !colorValue) {
93753
93815
  return;
@@ -93758,11 +93820,22 @@ function addSectionTitleColorContrastDiagnostic({
93758
93820
  background: colorValue
93759
93821
  });
93760
93822
  if (ratio !== null && ratio < TEXT_CONTRAST_THRESHOLD) {
93761
- diagnostics2.push({
93762
- type: "accessibility",
93763
- level: 1,
93764
- message: `${colorName2} has insufficient contrast for the section heading text${modeSuffix} (${ratio.toFixed(2)}:1; requires at least ${TEXT_CONTRAST_THRESHOLD}:1).`
93765
- });
93823
+ diagnostics2.push(
93824
+ codedDiagnostic({
93825
+ type: "accessibility",
93826
+ level: 1,
93827
+ code: "doenet-a0006",
93828
+ args: {
93829
+ colorName: colorName2,
93830
+ // Numbers, not the strings they used to be formatted
93831
+ // into: a locale that writes 4,50 rather than 4.50 can
93832
+ // only do so if the value arrives as a number.
93833
+ ratio,
93834
+ threshold: TEXT_CONTRAST_THRESHOLD,
93835
+ mode
93836
+ }
93837
+ })
93838
+ );
93766
93839
  }
93767
93840
  }
93768
93841
  class SectioningComponent extends BlockComponent {
@@ -94632,7 +94705,7 @@ class SectioningComponent extends BlockComponent {
94632
94705
  colorName: darkSource?.colorName ?? stateKey,
94633
94706
  textColor: "#ffffff",
94634
94707
  canvasColor: CANVAS_DARK_MODE_COLOR,
94635
- modeSuffix: " (dark mode)"
94708
+ mode: "dark"
94636
94709
  });
94637
94710
  }
94638
94711
  }
@@ -94921,21 +94994,27 @@ class SectioningComponent extends BlockComponent {
94921
94994
  if (desiredVariant.index !== void 0) {
94922
94995
  let desiredVariantIndex = Number(desiredVariant.index);
94923
94996
  if (!Number.isFinite(desiredVariantIndex)) {
94924
- core2.addDiagnostic({
94925
- type: "info",
94926
- message: "Variant index " + desiredVariant.index + " must be a number",
94927
- position: serializedComponent.position,
94928
- sourceDoc: serializedComponent.sourceDoc
94929
- });
94930
- variantIndex = 1;
94931
- } else {
94932
- if (!Number.isInteger(desiredVariantIndex)) {
94933
- core2.addDiagnostic({
94997
+ core2.addDiagnostic(
94998
+ codedDiagnostic({
94934
94999
  type: "info",
94935
- message: "Variant index " + desiredVariant.index + " must be an integer",
95000
+ code: "doenet-i0010",
95001
+ args: { index: String(desiredVariant.index) },
94936
95002
  position: serializedComponent.position,
94937
95003
  sourceDoc: serializedComponent.sourceDoc
94938
- });
95004
+ })
95005
+ );
95006
+ variantIndex = 1;
95007
+ } else {
95008
+ if (!Number.isInteger(desiredVariantIndex)) {
95009
+ core2.addDiagnostic(
95010
+ codedDiagnostic({
95011
+ type: "info",
95012
+ code: "doenet-i0011",
95013
+ args: { index: String(desiredVariant.index) },
95014
+ position: serializedComponent.position,
95015
+ sourceDoc: serializedComponent.sourceDoc
95016
+ })
95017
+ );
94939
95018
  desiredVariantIndex = Math.round(desiredVariantIndex);
94940
95019
  }
94941
95020
  let indexFrom0 = (desiredVariantIndex - 1) % numVariants;
@@ -101213,24 +101292,6 @@ function returnLineFamilyLabelPositionAttribute() {
101213
101292
  description: "Where the label sits along this line/curve."
101214
101293
  };
101215
101294
  }
101216
- function codedDiagnostic({
101217
- type,
101218
- code,
101219
- args,
101220
- position: position2,
101221
- sourceDoc,
101222
- level
101223
- }) {
101224
- return {
101225
- type,
101226
- message: formatEnglishDiagnostic(code, args),
101227
- code,
101228
- ...args === void 0 ? {} : { args },
101229
- ...position2 === void 0 ? {} : { position: position2 },
101230
- ...sourceDoc === void 0 ? {} : { sourceDoc },
101231
- ...level === void 0 ? {} : { level }
101232
- };
101233
- }
101234
101295
  class Line extends GraphicalComponent {
101235
101296
  constructor(args) {
101236
101297
  super(args);
@@ -111698,10 +111759,13 @@ class ComponentWithSelectableType extends BaseComponent {
111698
111759
  if (!type) {
111699
111760
  type = "number";
111700
111761
  } else if (!["number", "letters", "math", "text", "boolean"].includes(type)) {
111701
- diagnostics2.push({
111702
- message: `Invalid type ${type}, setting type to number.`,
111703
- type: "warning"
111704
- });
111762
+ diagnostics2.push(
111763
+ codedDiagnostic({
111764
+ type: "warning",
111765
+ code: "doenet-w0016",
111766
+ args: { type }
111767
+ })
111768
+ );
111705
111769
  type = "number";
111706
111770
  }
111707
111771
  let componentType = type === "letters" ? "text" : type;
@@ -111766,10 +111830,16 @@ class ComponentWithSelectableType extends BaseComponent {
111766
111830
  } else if (!["number", "letters", "math", "text", "boolean"].includes(
111767
111831
  type
111768
111832
  )) {
111769
- diagnostics2.push({
111770
- message: `Invalid type ${type}, setting type to number.`,
111771
- type: "info"
111772
- });
111833
+ diagnostics2.push(
111834
+ codedDiagnostic({
111835
+ // Info here, a warning at the other three call
111836
+ // sites. The code names the situation, not the
111837
+ // severity, so they share it.
111838
+ type: "info",
111839
+ code: "doenet-w0016",
111840
+ args: { type }
111841
+ })
111842
+ );
111773
111843
  type = "number";
111774
111844
  }
111775
111845
  return { setValue: { type }, sendDiagnostics: diagnostics2 };
@@ -111868,10 +111938,13 @@ class ComponentListWithSelectableType extends ComponentWithSelectableType {
111868
111938
  } else if (!["number", "letters", "math", "text", "boolean"].includes(
111869
111939
  type
111870
111940
  )) {
111871
- diagnostics2.push({
111872
- message: `Invalid type ${type}, setting type to number.`,
111873
- type: "warning"
111874
- });
111941
+ diagnostics2.push(
111942
+ codedDiagnostic({
111943
+ type: "warning",
111944
+ code: "doenet-w0016",
111945
+ args: { type }
111946
+ })
111947
+ );
111875
111948
  type = "number";
111876
111949
  }
111877
111950
  let componentType = type === "letters" ? "text" : type;
@@ -112032,10 +112105,13 @@ class ComponentListOfListsWithSelectableType extends ComponentWithSelectableType
112032
112105
  if (!type) {
112033
112106
  type = "number";
112034
112107
  } else if (!["number", "letters", "math", "text", "boolean"].includes(type)) {
112035
- diagnostics2.push({
112036
- message: `Invalid type ${type}, setting type to number.`,
112037
- type: "warning"
112038
- });
112108
+ diagnostics2.push(
112109
+ codedDiagnostic({
112110
+ type: "warning",
112111
+ code: "doenet-w0016",
112112
+ args: { type }
112113
+ })
112114
+ );
112039
112115
  type = "number";
112040
112116
  }
112041
112117
  const newChildren = results.pieces.map((x2) => ({
@@ -112437,10 +112513,13 @@ class SideBySide extends BlockComponent {
112437
112513
  }
112438
112514
  }
112439
112515
  if (foundAbsolute) {
112440
- diagnostics2.push({
112441
- message: "`<sideBySide>` is not implemented for absolute measurements. Setting widths to relative.",
112442
- type: "warning"
112443
- });
112516
+ diagnostics2.push(
112517
+ codedDiagnostic({
112518
+ type: "warning",
112519
+ code: "doenet-w0018",
112520
+ args: { component: "sideBySide" }
112521
+ })
112522
+ );
112444
112523
  }
112445
112524
  widthsAbsolute = false;
112446
112525
  allWidthsSpecified = allWidthsSpecified.map(
@@ -112570,10 +112649,13 @@ class SideBySide extends BlockComponent {
112570
112649
  );
112571
112650
  }
112572
112651
  if (secondMarginAbsolute || marginsAbsolute) {
112573
- diagnostics2.push({
112574
- message: "`<sideBySide>` is not implemented for absolute measurements. Setting margins to relative.",
112575
- type: "warning"
112576
- });
112652
+ diagnostics2.push(
112653
+ codedDiagnostic({
112654
+ type: "warning",
112655
+ code: "doenet-w0019",
112656
+ args: { component: "sideBySide" }
112657
+ })
112658
+ );
112577
112659
  }
112578
112660
  marginsAbsolute = false;
112579
112661
  return {
@@ -112705,10 +112787,13 @@ class SideBySide extends BlockComponent {
112705
112787
  } else if (dependencyValues.numPanels === 1) {
112706
112788
  allMargins[1] = 100 - (allMargins[0] + allWidths[0]);
112707
112789
  } else {
112708
- diagnostics2.push({
112709
- message: "Invalid `<sideBySide>`: it must have at least one block child.",
112710
- type: "warning"
112711
- });
112790
+ diagnostics2.push(
112791
+ codedDiagnostic({
112792
+ type: "warning",
112793
+ code: "doenet-w0020",
112794
+ args: { component: "sideBySide" }
112795
+ })
112796
+ );
112712
112797
  }
112713
112798
  }
112714
112799
  }
@@ -113445,10 +113530,13 @@ class SbsGroup extends BlockComponent {
113445
113530
  }
113446
113531
  }
113447
113532
  if (foundAbsolute) {
113448
- diagnostics2.push({
113449
- message: "`<sbsGroup>` is not implemented for absolute measurements. Setting widths to relative.",
113450
- type: "warning"
113451
- });
113533
+ diagnostics2.push(
113534
+ codedDiagnostic({
113535
+ type: "warning",
113536
+ code: "doenet-w0018",
113537
+ args: { component: "sbsGroup" }
113538
+ })
113539
+ );
113452
113540
  }
113453
113541
  widthsAbsolute = false;
113454
113542
  return {
@@ -113637,10 +113725,13 @@ class SbsGroup extends BlockComponent {
113637
113725
  }
113638
113726
  }
113639
113727
  if (foundAbsolute) {
113640
- diagnostics2.push({
113641
- message: "`<sbsGroup>` is not implemented for absolute measurements. Setting margins to relative.",
113642
- type: "warning"
113643
- });
113728
+ diagnostics2.push(
113729
+ codedDiagnostic({
113730
+ type: "warning",
113731
+ code: "doenet-w0019",
113732
+ args: { component: "sbsGroup" }
113733
+ })
113734
+ );
113644
113735
  }
113645
113736
  marginsAbsolute = false;
113646
113737
  return {
@@ -113771,10 +113862,13 @@ class SbsGroup extends BlockComponent {
113771
113862
  } else if (dependencyValues.maxNPanelsPerRow === 1) {
113772
113863
  allMargins[1] = 100 - (allMargins[0] + allWidths[0]);
113773
113864
  } else {
113774
- diagnostics2.push({
113775
- message: "Invalid `<sbsGroup>`: it must have at least one block child.",
113776
- type: "warning"
113777
- });
113865
+ diagnostics2.push(
113866
+ codedDiagnostic({
113867
+ type: "warning",
113868
+ code: "doenet-w0020",
113869
+ args: { component: "sbsGroup" }
113870
+ })
113871
+ );
113778
113872
  }
113779
113873
  }
113780
113874
  }
@@ -115433,12 +115527,21 @@ class Input extends InlineComponent {
115433
115527
  dependencyValues.externalLabelsReferencingInputByFor?.length
115434
115528
  );
115435
115529
  if (shortDescription === "" && !dependencyValues.label && !hasExternalForLabel) {
115436
- let objectNeedingLabel = dependencyValues.createdFromSugar && dependencyValues.answerAncestor ? "an `<answer>` creating an input" : `\`<${componentClass.componentType}>\``;
115437
- diagnostics2.push({
115438
- type: "accessibility",
115439
- level: 1,
115440
- message: `For accessibility, ${objectNeedingLabel} must have a short description or a label.`
115441
- });
115530
+ const createdByAnswer = dependencyValues.createdFromSugar && dependencyValues.answerAncestor;
115531
+ diagnostics2.push(
115532
+ createdByAnswer ? codedDiagnostic({
115533
+ type: "accessibility",
115534
+ level: 1,
115535
+ code: "doenet-a0004"
115536
+ }) : codedDiagnostic({
115537
+ type: "accessibility",
115538
+ level: 1,
115539
+ code: "doenet-a0003",
115540
+ args: {
115541
+ component: componentClass.componentType
115542
+ }
115543
+ })
115544
+ );
115442
115545
  }
115443
115546
  return {
115444
115547
  setValue: { shortDescription },
@@ -120696,21 +120799,27 @@ class Document extends BaseComponent {
120696
120799
  if (desiredVariant.index !== void 0) {
120697
120800
  let desiredVariantIndex = Number(desiredVariant.index);
120698
120801
  if (!Number.isFinite(desiredVariantIndex)) {
120699
- core2.addDiagnostic({
120700
- type: "info",
120701
- message: "Variant index " + desiredVariant.index + " must be a number",
120702
- position: serializedComponent.position,
120703
- sourceDoc: serializedComponent.sourceDoc
120704
- });
120705
- variantIndex = 1;
120706
- } else {
120707
- if (!Number.isInteger(desiredVariantIndex)) {
120708
- core2.addDiagnostic({
120802
+ core2.addDiagnostic(
120803
+ codedDiagnostic({
120709
120804
  type: "info",
120710
- message: "Variant index " + desiredVariant.index + " must be an integer",
120805
+ code: "doenet-i0010",
120806
+ args: { index: String(desiredVariant.index) },
120711
120807
  position: serializedComponent.position,
120712
120808
  sourceDoc: serializedComponent.sourceDoc
120713
- });
120809
+ })
120810
+ );
120811
+ variantIndex = 1;
120812
+ } else {
120813
+ if (!Number.isInteger(desiredVariantIndex)) {
120814
+ core2.addDiagnostic(
120815
+ codedDiagnostic({
120816
+ type: "info",
120817
+ code: "doenet-i0011",
120818
+ args: { index: String(desiredVariant.index) },
120819
+ position: serializedComponent.position,
120820
+ sourceDoc: serializedComponent.sourceDoc
120821
+ })
120822
+ );
120714
120823
  desiredVariantIndex = Math.round(desiredVariantIndex);
120715
120824
  }
120716
120825
  let indexFrom0 = (desiredVariantIndex - 1) % numVariants;
@@ -145132,11 +145241,13 @@ class Choiceinput extends Input {
145132
145241
  }
145133
145242
  const diagnostics2 = [];
145134
145243
  if (dependencyValues.labelPositionAttr && !isInline) {
145135
- diagnostics2.push({
145136
- message: "labelPosition is ignored for non-inline choiceInput",
145137
- type: "warning",
145138
- position: dependencyValues.labelPositionAttr.position
145139
- });
145244
+ diagnostics2.push(
145245
+ codedDiagnostic({
145246
+ type: "warning",
145247
+ code: "doenet-w0012",
145248
+ position: dependencyValues.labelPositionAttr.position
145249
+ })
145250
+ );
145140
145251
  }
145141
145252
  return {
145142
145253
  setValue,
@@ -145206,10 +145317,12 @@ class Choiceinput extends Input {
145206
145317
  let desiredChoiceOrder = dependencyValues.variants?.desiredVariant?.indices;
145207
145318
  if (desiredChoiceOrder !== void 0) {
145208
145319
  if (desiredChoiceOrder.length !== numChoices) {
145209
- diagnostics2.push({
145210
- message: "Ignoring indices specified for choiceInput as number of indices doesn't match number of choice children.",
145211
- type: "info"
145212
- });
145320
+ diagnostics2.push(
145321
+ codedDiagnostic({
145322
+ type: "info",
145323
+ code: "doenet-i0004"
145324
+ })
145325
+ );
145213
145326
  } else {
145214
145327
  desiredChoiceOrder = desiredChoiceOrder.map(Number);
145215
145328
  if (!desiredChoiceOrder.every(Number.isInteger)) {
@@ -145220,10 +145333,13 @@ class Choiceinput extends Input {
145220
145333
  if (!desiredChoiceOrder.every(
145221
145334
  (x2) => x2 >= 1 && x2 <= numChoices
145222
145335
  )) {
145223
- diagnostics2.push({
145224
- message: "Ignoring indices specified for choiceInput as some indices out of range.",
145225
- type: "info"
145226
- });
145336
+ diagnostics2.push(
145337
+ codedDiagnostic({
145338
+ type: "info",
145339
+ code: "doenet-i0007",
145340
+ args: { component: "choiceInput" }
145341
+ })
145342
+ );
145227
145343
  } else {
145228
145344
  return {
145229
145345
  setValue: {
@@ -151907,11 +152023,14 @@ let Graph$1 = class Graph extends BlockComponent {
151907
152023
  shortDescription = shortDescriptionChild.stateValues.text.trim();
151908
152024
  }
151909
152025
  if (shortDescription === "" && !dependencyValues.decorative) {
151910
- diagnostics2.push({
151911
- type: "accessibility",
151912
- level: 1,
151913
- message: "For accessibility, `<graph>` must either have a short description or be specified as decorative."
151914
- });
152026
+ diagnostics2.push(
152027
+ codedDiagnostic({
152028
+ type: "accessibility",
152029
+ level: 1,
152030
+ code: "doenet-a0001",
152031
+ args: { component: "graph" }
152032
+ })
152033
+ );
151915
152034
  }
151916
152035
  return {
151917
152036
  setValue: { shortDescription },
@@ -158558,14 +158677,14 @@ class ConstrainTo extends ConstraintComponent {
158558
158677
  let diagnostics2 = [];
158559
158678
  for (let child of dependencyValues.graphicalChildren) {
158560
158679
  if (!child.stateValues.nearestPoint) {
158561
- const warning = {
158562
- type: "warning",
158563
- message: `Cannot constrain to a \`<${child.componentType}>\` as it doesn't have a nearestPoint state variable.`
158564
- };
158565
- if (child.position) {
158566
- warning.position = child.position;
158567
- }
158568
- diagnostics2.push(warning);
158680
+ diagnostics2.push(
158681
+ codedDiagnostic({
158682
+ type: "warning",
158683
+ code: "doenet-w0010",
158684
+ args: { component: child.componentType },
158685
+ position: child.position || void 0
158686
+ })
158687
+ );
158569
158688
  continue;
158570
158689
  }
158571
158690
  nearestPointFunctions.push(child.stateValues.nearestPoint);
@@ -158785,14 +158904,14 @@ class AttractTo extends ConstraintComponent {
158785
158904
  let diagnostics2 = [];
158786
158905
  for (let child of dependencyValues.graphicalChildren) {
158787
158906
  if (!child.stateValues.nearestPoint) {
158788
- const warning = {
158789
- type: "warning",
158790
- message: `Cannot attract to a \`<${child.componentType}>\` as it doesn't have a nearestPoint state variable.`
158791
- };
158792
- if (child.position) {
158793
- warning.position = child.position;
158794
- }
158795
- diagnostics2.push(warning);
158907
+ diagnostics2.push(
158908
+ codedDiagnostic({
158909
+ type: "warning",
158910
+ code: "doenet-w0009",
158911
+ args: { component: child.componentType },
158912
+ position: child.position || void 0
158913
+ })
158914
+ );
158796
158915
  continue;
158797
158916
  }
158798
158917
  nearestPointFunctions.push(child.stateValues.nearestPoint);
@@ -159143,14 +159262,14 @@ class ConstrainToInterior extends ConstraintComponent {
159143
159262
  let diagnostics2 = [];
159144
159263
  for (let child of dependencyValues.graphicalChildren) {
159145
159264
  if (!child.stateValues.nearestPoint) {
159146
- const warning = {
159147
- type: "warning",
159148
- message: `Cannot constrain to interior of a \`<${child.componentType}>\` as it doesn't have a nearestPoint state variable.`
159149
- };
159150
- if (child.position) {
159151
- warning.position = child.position;
159152
- }
159153
- diagnostics2.push(warning);
159265
+ diagnostics2.push(
159266
+ codedDiagnostic({
159267
+ type: "warning",
159268
+ code: "doenet-w0011",
159269
+ args: { component: child.componentType },
159270
+ position: child.position || void 0
159271
+ })
159272
+ );
159154
159273
  continue;
159155
159274
  }
159156
159275
  let fs = { nearestPoint: child.stateValues.nearestPoint };
@@ -208482,11 +208601,14 @@ class Image extends BlockComponent {
208482
208601
  shortDescription = shortDescriptionChild.stateValues.text.trim();
208483
208602
  }
208484
208603
  if (shortDescription === "" && !dependencyValues.decorative) {
208485
- diagnostics2.push({
208486
- type: "accessibility",
208487
- level: 1,
208488
- message: "For accessibility, `<image>` must either have a short description or be specified as decorative."
208489
- });
208604
+ diagnostics2.push(
208605
+ codedDiagnostic({
208606
+ type: "accessibility",
208607
+ level: 1,
208608
+ code: "doenet-a0001",
208609
+ args: { component: "image" }
208610
+ })
208611
+ );
208490
208612
  }
208491
208613
  return {
208492
208614
  setValue: { shortDescription },
@@ -209092,11 +209214,13 @@ class Video extends BlockComponent {
209092
209214
  shortDescription = shortDescriptionChild.stateValues.text.trim();
209093
209215
  }
209094
209216
  if (shortDescription === "") {
209095
- diagnostics2.push({
209096
- type: "accessibility",
209097
- level: 1,
209098
- message: "For accessibility, `<video>` must have a short description."
209099
- });
209217
+ diagnostics2.push(
209218
+ codedDiagnostic({
209219
+ type: "accessibility",
209220
+ level: 1,
209221
+ code: "doenet-a0002"
209222
+ })
209223
+ );
209100
209224
  }
209101
209225
  return {
209102
209226
  setValue: { shortDescription },
@@ -216505,19 +216629,25 @@ class Sort extends CompositeComponent {
216505
216629
  type = componentAttributes.type.value;
216506
216630
  } else {
216507
216631
  if (matchedChildren.some((child) => typeof child === "string")) {
216508
- diagnostics2.push({
216509
- type: "warning",
216510
- message: `For \`<sort>\` to work with string children, a \`type\` attribute must be specified.`
216511
- });
216632
+ diagnostics2.push(
216633
+ codedDiagnostic({
216634
+ type: "warning",
216635
+ code: "doenet-w0013",
216636
+ args: { component: "sort" }
216637
+ })
216638
+ );
216512
216639
  }
216513
216640
  return { success: false, diagnostics: diagnostics2 };
216514
216641
  }
216515
216642
  if (!["math", "text", "number", "boolean"].includes(type)) {
216516
216643
  console.warn(`Invalid type ${type}`);
216517
- diagnostics2.push({
216518
- type: "warning",
216519
- message: `Invalid type ${type} for sort component. Must be one of math, text, number, or boolean. Defaulting to math.`
216520
- });
216644
+ diagnostics2.push(
216645
+ codedDiagnostic({
216646
+ type: "warning",
216647
+ code: "doenet-w0014",
216648
+ args: { type, component: "sort" }
216649
+ })
216650
+ );
216521
216651
  type = "math";
216522
216652
  }
216523
216653
  let groupIntoComponentTypesSeparatedBySpaces = returnGroupIntoComponentTypeSeparatedBySpacesOutsideParens({
@@ -216581,10 +216711,13 @@ class Sort extends CompositeComponent {
216581
216711
  const diagnostics2 = [];
216582
216712
  for (let child of dependencyValues.children) {
216583
216713
  if (typeof child === "string") {
216584
- diagnostics2.push({
216585
- type: "warning",
216586
- message: `String "${child}" is not a valid component to sort. Ignoring.`
216587
- });
216714
+ diagnostics2.push(
216715
+ codedDiagnostic({
216716
+ type: "warning",
216717
+ code: "doenet-w0015",
216718
+ args: { value: child, component: "sort" }
216719
+ })
216720
+ );
216588
216721
  continue;
216589
216722
  }
216590
216723
  if (child.stateValues.componentIndicesInList) {
@@ -216915,19 +217048,25 @@ class Shuffle extends CompositeComponent {
216915
217048
  type = componentAttributes.type.value;
216916
217049
  } else {
216917
217050
  if (matchedChildren.some((child) => typeof child === "string")) {
216918
- diagnostics2.push({
216919
- type: "warning",
216920
- message: `For \`<shuffle>\` to work with string children, a \`type\` attribute must be specified.`
216921
- });
217051
+ diagnostics2.push(
217052
+ codedDiagnostic({
217053
+ type: "warning",
217054
+ code: "doenet-w0013",
217055
+ args: { component: "shuffle" }
217056
+ })
217057
+ );
216922
217058
  }
216923
217059
  return { success: false, diagnostics: diagnostics2 };
216924
217060
  }
216925
217061
  if (!["math", "text", "number", "boolean"].includes(type)) {
216926
217062
  console.warn(`Invalid type ${type}`);
216927
- diagnostics2.push({
216928
- type: "warning",
216929
- message: `Invalid type ${type} for shuffle component. Must be one of math, text, number, or boolean. Defaulting to math.`
216930
- });
217063
+ diagnostics2.push(
217064
+ codedDiagnostic({
217065
+ type: "warning",
217066
+ code: "doenet-w0014",
217067
+ args: { type, component: "shuffle" }
217068
+ })
217069
+ );
216931
217070
  type = "math";
216932
217071
  }
216933
217072
  let groupIntoComponentTypesSeparatedBySpaces = returnGroupIntoComponentTypeSeparatedBySpacesOutsideParens({
@@ -216981,10 +217120,13 @@ class Shuffle extends CompositeComponent {
216981
217120
  const diagnostics2 = [];
216982
217121
  for (let child of dependencyValues.children) {
216983
217122
  if (typeof child === "string") {
216984
- diagnostics2.push({
216985
- type: "warning",
216986
- message: `String "${child}" is not a valid component to shuffle. Ignoring.`
216987
- });
217123
+ diagnostics2.push(
217124
+ codedDiagnostic({
217125
+ type: "warning",
217126
+ code: "doenet-w0015",
217127
+ args: { value: child, component: "shuffle" }
217128
+ })
217129
+ );
216988
217130
  }
216989
217131
  if (child.stateValues?.componentIndicesInList) {
216990
217132
  originalComponentIndices.push(
@@ -217031,10 +217173,12 @@ class Shuffle extends CompositeComponent {
217031
217173
  let desiredComponentOrder = dependencyValues.variants?.desiredVariant?.indices;
217032
217174
  if (desiredComponentOrder !== void 0) {
217033
217175
  if (desiredComponentOrder.length !== numComponents) {
217034
- diagnostics2.push({
217035
- message: "Ignoring indices specified for shuffle as number of indices doesn't match number of components.",
217036
- type: "info"
217037
- });
217176
+ diagnostics2.push(
217177
+ codedDiagnostic({
217178
+ type: "info",
217179
+ code: "doenet-i0006"
217180
+ })
217181
+ );
217038
217182
  } else {
217039
217183
  desiredComponentOrder = desiredComponentOrder.map(Number);
217040
217184
  if (!desiredComponentOrder.every(Number.isInteger)) {
@@ -217045,10 +217189,13 @@ class Shuffle extends CompositeComponent {
217045
217189
  if (!desiredComponentOrder.every(
217046
217190
  (x2) => x2 >= 1 && x2 <= numComponents
217047
217191
  )) {
217048
- diagnostics2.push({
217049
- message: "Ignoring indices specified for shuffle as some indices out of range.",
217050
- type: "info"
217051
- });
217192
+ diagnostics2.push(
217193
+ codedDiagnostic({
217194
+ type: "info",
217195
+ code: "doenet-i0007",
217196
+ args: { component: "shuffle" }
217197
+ })
217198
+ );
217052
217199
  } else {
217053
217200
  return {
217054
217201
  setValue: {
@@ -225360,10 +225507,12 @@ class PretzelArranger extends CompositeComponent {
225360
225507
  let desiredProblemOrder = dependencyValues.variants?.desiredVariant?.indices;
225361
225508
  if (desiredProblemOrder !== void 0) {
225362
225509
  if (desiredProblemOrder.length !== numProblems) {
225363
- diagnostics2.push({
225364
- message: "Ignoring indices specified for problem as number of indices doesn't match number of problem children.",
225365
- type: "info"
225366
- });
225510
+ diagnostics2.push(
225511
+ codedDiagnostic({
225512
+ type: "info",
225513
+ code: "doenet-i0005"
225514
+ })
225515
+ );
225367
225516
  } else {
225368
225517
  desiredProblemOrder = desiredProblemOrder.map(Number);
225369
225518
  if (!desiredProblemOrder.every(Number.isInteger)) {
@@ -225374,20 +225523,27 @@ class PretzelArranger extends CompositeComponent {
225374
225523
  if (!desiredProblemOrder.every(
225375
225524
  (x2) => x2 >= 1 && x2 <= numProblems
225376
225525
  )) {
225377
- diagnostics2.push({
225378
- message: "Ignoring indices specified for pretzel as some indices out of range.",
225379
- type: "info"
225380
- });
225526
+ diagnostics2.push(
225527
+ codedDiagnostic({
225528
+ type: "info",
225529
+ code: "doenet-i0007",
225530
+ args: { component: "pretzel" }
225531
+ })
225532
+ );
225381
225533
  } else if (new Set(desiredProblemOrder).size !== numProblems) {
225382
- diagnostics2.push({
225383
- message: "Ignoring indices specified for pretzel as some indices are repeated.",
225384
- type: "info"
225385
- });
225534
+ diagnostics2.push(
225535
+ codedDiagnostic({
225536
+ type: "info",
225537
+ code: "doenet-i0008"
225538
+ })
225539
+ );
225386
225540
  } else if (mode === "circuit" && numProblems > 0 && desiredProblemOrder[0] !== 1) {
225387
- diagnostics2.push({
225388
- message: "Ignoring indices specified for pretzel in circuit mode as the first index must be 1.",
225389
- type: "info"
225390
- });
225541
+ diagnostics2.push(
225542
+ codedDiagnostic({
225543
+ type: "info",
225544
+ code: "doenet-i0009"
225545
+ })
225546
+ );
225391
225547
  } else {
225392
225548
  return {
225393
225549
  setValue: {
@@ -226416,11 +226572,14 @@ class ShortDescription extends TextOrInline {
226416
226572
  }
226417
226573
  const diagnostics2 = [];
226418
226574
  if (foundMathType) {
226419
- diagnostics2.push({
226420
- type: "accessibility",
226421
- level: 2,
226422
- message: `Short descriptions should not contain math components such as \`<${foundMathType}>\`. Spell out any math with words.`
226423
- });
226575
+ diagnostics2.push(
226576
+ codedDiagnostic({
226577
+ type: "accessibility",
226578
+ level: 2,
226579
+ code: "doenet-a0005",
226580
+ args: { component: foundMathType }
226581
+ })
226582
+ );
226424
226583
  }
226425
226584
  return { setValue: { value }, sendDiagnostics: diagnostics2 };
226426
226585
  }
@@ -229764,10 +229923,13 @@ class VariableNameList extends MathList {
229764
229923
  let variable = dependencyValuesByKey[arrayKey].math;
229765
229924
  let validVariable = isValidVariable(variable);
229766
229925
  if (!validVariable) {
229767
- diagnostics2.push({
229768
- message: "Invalid value of a variable: `" + variable.toString() + "`",
229769
- type: "warning"
229770
- });
229926
+ diagnostics2.push(
229927
+ codedDiagnostic({
229928
+ type: "warning",
229929
+ code: "doenet-w0017",
229930
+ args: { value: variable.toString() }
229931
+ })
229932
+ );
229771
229933
  validVariable = false;
229772
229934
  }
229773
229935
  variables2[arrayKey] = variable;
@@ -229812,10 +229974,15 @@ class Variable extends MathComponent {
229812
229974
  dependencyValues.valuePreValidate
229813
229975
  );
229814
229976
  if (!validVariable) {
229815
- diagnostics2.push({
229816
- message: "Invalid value of a variable: `" + dependencyValues.valuePreValidate.toString() + "`",
229817
- type: "warning"
229818
- });
229977
+ diagnostics2.push(
229978
+ codedDiagnostic({
229979
+ type: "warning",
229980
+ code: "doenet-w0017",
229981
+ args: {
229982
+ value: dependencyValues.valuePreValidate.toString()
229983
+ }
229984
+ })
229985
+ );
229819
229986
  }
229820
229987
  return {
229821
229988
  setValue: {
@@ -232849,4 +233016,4 @@ export {
232849
233016
  getDefaultExportFromCjs as g,
232850
233017
  updateSyntaxFromV06toV07 as u
232851
233018
  };
232852
- //# sourceMappingURL=index-NJbOIT2j.js.map
233019
+ //# sourceMappingURL=index-RygVZ98K.js.map