Skip to content

refactor(Button,Textarea): deprecate three props that render nothing, and close the #63 test gaps - #529

Merged
IgorShevchik merged 6 commits into
mainfrom
claude/repo-rules-35um4e
Sep 2, 2026
Merged

refactor(Button,Textarea): deprecate three props that render nothing, and close the #63 test gaps#529
IgorShevchik merged 6 commits into
mainfrom
claude/repo-rules-35um4e

Conversation

@IgorShevchik

@IgorShevchik IgorShevchik commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Linked issue

Refs #63 (closes §1 and §2; §3 was already done — see below)

Type of change

  • Documentation (updates to the documentation or readme)
  • Bug fix (a non-breaking change that fixes an issue)
  • Enhancement (improving an existing functionality)
  • New feature (a non-breaking change that adds functionality)
  • Chore (updates to the build process or auxiliary tools and libraries)
  • Revert (undoing a merged change — retitle this PR revert(Scope): ...)
  • Breaking change (fix or feature that would cause existing functionality to change)

Description

Three parts, in the order they happened: the tests came first, the deprecations are what the tests turned up, and the docs change is what the review panel found missing.

Squash note. The subject is refactor(...) on purpose, so the deprecation reaches the changelog. Under release-please-config.json, refactor maps to the Chore section; a test: subject would have filed a public-API deprecation under Tests, where nobody looks for one.

Reviewed by the five-reviewer panel — findings and what was verified independently, and how the two open items were closed.


Part 1 — three props deprecated

All three are typed, JSDoc'd and forwarded to the theme. None of them changes a single byte of rendered markup. Measured, not inferred: each component was mounted with and without the prop and the HTML diffed.

Prop Why it is inert
Button.depth The depth compound variants in src/theme/button.ts are keyed on the legacy colour names (default, danger, success, primary, …), never on air-*. The default colour is air-secondary-no-accent.
Button.activeDepth Same mechanism, same result.
Textarea.fixed Works through fixed × size compound variants. src/theme/input.ts has five of them; src/theme/textarea.ts has none — and declares fixed: { false: '' } with no true branch at all — because Textarea deliberately has no size (// @memo we remove size).

depth: 'dark' changes the DOM on color: 'primary' and does not on the default — that is the measurement, not a reading of the theme.

Button.depth was already meant to be deprecated. It carried the note as @depricate, misspelled, so no IDE, no vue-tsc and no docs generator ever saw it. This spells the tag correctly, gives it a reason, and adds the @removed 3.0.0 tag the repo's existing deprecation blocks all carry.

fixed is declared on ten components. Only Textarea's is inert — the other nine (Input, InputDate, InputMenu, InputNumber, InputTags, InputTime, PinInput, Select, SelectMenu) were probed the same way and all nine render. The tag goes on Textarea alone.

Nothing is removed and no behaviour changes — both are 3.0.0 work. The existing tests that exercise depth on legacy colours stay, so the behaviour is pinned until then.


Part 2 — the docs now read the tag

Raised by two reviewers independently: the deprecation would have been invisible where people actually look. Nothing under docs/app or docs/server read @deprecated — zero grep hits. The two props that carried a deprecation were dropped from the output by a hardcoded ['depth', 'activeDepth'] list in two places (ComponentProps.vue and transformMDC.ts), which left Textarea.fixed rendering as an ordinary prop while its JSDoc said it does nothing.

Extending those lists was never an option — they match on prop name with no component scoping, so adding fixed would have hidden it from the nine components where it works.

Both paths now read the tag:

  • Props table — a new ComponentPropsDeprecated.vue, built to mirror the existing ComponentPropsLinks.vue: a badge carrying the @removed version, and the @deprecated prose through MDC like any other description.
  • /raw/ markdown, the source llms.txt serves — the emitted JSDoc block now carries @deprecated and @removed lines.

Both hardcoded lists are gone, so depth and activeDepth reappear marked rather than vanishing. That is the point: someone with depth="dark" in their code needs somewhere to learn it is going away.

Verified rather than assumed — vue-component-meta's createChecker run directly over both components returns deprecated (full text, newlines intact) and removed (3.0.0) in props[].tags for all three props, and the new emitter produces:

  /**
   * Keep the mobile text size on all breakpoints. (Left for backward compatibility.)
   * @deprecated Does nothing. It works through `fixed` x `size` compound
   *   variants, and `Textarea` deliberately has no `size`, so no variant ever
   *   matches.
   * @removed 3.0.0
   */
  fixed?: boolean | undefined;

A prop with no deprecation emits byte-for-byte what it did before.

Not verified: the rendered page. The docs dev server does not start in this environment — @nuxtjs/mcp-toolkit throws completable is not defined from its own bundle, which nothing in this diff imports. nuxt typecheck docs, eslint and the four docs-facing specs all pass. Worth a look at the props table on the first docs deploy after merge.


Part 3 — the #63 test gaps

§1 — the missing axe cases

Six component specs had no accessibility case. Four get one: Advice, Countdown, ProsePrompt, TableWrapper.

ScrollArea and Theme are deliberately left without one. nuxt/ui@v4 skips exactly those two as well (its own gaps are DataSlot, Icon, ScrollArea, Theme), and the reason is visible in the source — Theme.vue is <template><slot /></template>, a renderless provider, so an axe run on it measures whatever the test happens to put in the slot rather than the component.

An axe test that runs no rules is green for free, so each case was checked by reading axe's own result object, not just its verdict. The first commit got two of the four wrong; the second fixes them:

Case axe rules passed, first commit now
TableWrapper 0 5
Countdown 0 3
Advice 1 3
ProsePrompt 3 3

Those figures count results.passes. Three of the four cases additionally report one incomplete rule — color-contrast, which happy-dom cannot evaluate without real layout — not counted above.

  • TableWrapper handed its table markup to the slot as a string, which Vue escapes to text — no table ever reached the DOM. Rebuilt with h.
  • Countdown's ring and digits match no axe rule at all; the case now mounts with an avatar, which renders an <img>.
  • Advice ran one rule: an icon sets isLeading, which wins the v-else-if and drops the avatar. The case passes the avatar instead.

Then each was checked against a real regression in its own component:

Spec Mutation Violation raised
Advice, Countdown :alt stripped from the avatar <img> in Avatar.vue image-alt
ProsePrompt :label stripped from the action buttons button-name
TableWrapper role="row" on the wrapper root aria-required-children, aria-required-parent

Worth recording: the first TableWrapper mutation check did go red, on aria-required-children — but for the wrong reason. There were no rows to find because the escaped string meant there was no table. A mutation going red is not by itself proof the test works.

These four cases are narrow by construction — each exercises the one prop combination that makes some rule fire. They do not speak for other configurations of the same components.

§2 — the untested props

A one-off scan over src/runtime/components/*.vue compared each component's declared props against its spec: 1140 props declared, 242 never mentioned in their own spec (21 %), and that is a floor — "mentioned" is not "exercised".

The concentration is the interesting part. The densest offenders are props nuxt/ui does not have:

                Input.vue  Select.vue   (upstream, fetched from raw.githubusercontent.com)
noPadding           0          0
noBorder            0          0
underline           0          0
tag                 0          0
tagColor            0          0

An upstream prop arrives with an upstream test. A Bitrix24-only prop arrives with nothing. So this adds cases for the Bitrix24-only props of the five densest components — Input, Textarea, Button, Select, InputNumber.

Only props that change rendered markup are pinned. Each candidate was measured first; the ones that render nothing (autofocus, autofocusDelay, autoresizeDelay, maxrows, loadingAuto, Select's content) are named in a comment in each spec instead. The three deprecations above came out of the same pass.

activeColor and activeDepth get behavioural tests rather than snapshot cases. Both resolve to a colour the snapshot matrix already renders, so a renderEach case for either one collides with a sibling — the #454 guard caught this and rejected the first draft. What is worth asserting is the override: the prop applies only while the button is active. Both tests go red when the active && guard is dropped from Button.vue.

No prop-coverage utility is added. The scan was run once by hand; the result is these tests. A standing checker would be another config to maintain, and #87 already settled the direction on home-grown test machinery. The measurement, the script and the caveats are recorded as item 6 on the sync-pipeline tracker so the finding outlives this PR.

§3 — behavioural tests

Already done, and ahead of upstream: 36 of 110 of our component specs carry behavioural assertions (trigger/keydown/emitted/focus) against 28 of 116 in nuxt/ui@v4. The issue's initial set is covered apart from Accordion, which is snapshot-only upstream too.


Numbers

  • Snapshot corpus 27,473,481 → 27,858,457 bytes (+376 KB, +1.4 %)
  • Snapshot entries 4380 → 4462 (+82)
  • Full suite after merging main: 340 files, 7804 passed, 6 skipped
  • pnpm lint and pnpm typecheck green (typecheck needs pnpm dev:prepare first — without it three pre-existing #app errors appear on clean main as well)

Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

🤖 Generated with Claude Code

https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc

Closes the two halves of #63 that hold up, and records why the third one
does not need doing.

**Accessibility (#63 §1).** Six component specs had no `axe` case. Four get
one here: `Advice`, `Countdown`, `ProsePrompt`, `TableWrapper`. `ScrollArea`
and `Theme` are left alone on purpose — `nuxt/ui@v4` skips both for the same
reason, `Theme` being `<template><slot /></template>`, so an `axe` run on it
measures the slot content and not the component.

Each of the four was verified to go red on a mutation of its own component:
a stripped `:label` on the prompt's action buttons (`button-name`),
`role="img"` on the decorative SVG in `Advice` and `Countdown`
(`svg-img-alt`), `role="table"` on the `TableWrapper` root
(`aria-required-children`).

**Prop coverage (#63 §2).** Of 1140 declared props across the library, 242
were never mentioned in their own spec, and the concentration is in props
`nuxt/ui` does not have — so nothing that arrives with an upstream sync will
ever cover them. This adds cases for the Bitrix24-only props of `Input`,
`Textarea`, `Button`, `Select` and `InputNumber`, keeping to the ones that
change rendered markup; props that only move focus or need real layout are
listed in a comment instead of pinned by a snapshot that would prove nothing.

`activeColor` and `activeDepth` get behavioural tests rather than snapshot
cases: both land on a colour the matrix already renders, so a `renderEach`
case for either collides with a sibling (#454). The assertion that matters is
the override — the prop applies only while the button is active — and it goes
red when the `active &&` guard is dropped.

No standing prop-coverage utility is added. The scan was a one-off; the
result is these tests.

**Behavioural tests (#63 §3).** Already done: 36 of 110 component specs carry
behavioural assertions against 28 of 116 upstream. Of the issue's initial set,
`Select`, `SelectMenu` and `Modal` are covered; `Accordion` is snapshot-only
upstream too.

Two findings surfaced by the scan, neither fixed here:

- `Textarea`'s `fixed` prop is inert. It works through `fixed x size` compound
  variants and `Textarea` deliberately has no `size`, so the prop is typed,
  documented and incapable of doing anything. Removing it is a public API
  change.
- `depth` and `activeDepth` on `Button` have compound variants only for the
  legacy colour names, so they render nothing on the `air-*` colours — which
  includes the default.

Snapshot corpus 27,473,481 -> 27,816,139 bytes (+335 KB, +1.2%).

Refs #63
Review of the first commit found that two of the four new accessibility
tests were green by vacancy, and that my mutation check on one of them had
passed for the wrong reason.

Measured by reading axe's own result object rather than only its pass/fail:

| Case | rules run, before | after |
| --- | --- | --- |
| `TableWrapper` | 0 | 5 |
| `Countdown` | 0 | 3 |
| `Advice` | 1 | 3 |
| `ProsePrompt` | 3 | 3 |

- `TableWrapper` handed its table markup to the slot as a **string**, which
  Vue escapes to text, so no table ever reached the DOM. Rebuilt with `h`.
  The earlier `role="table"` mutation did go red, but on
  `aria-required-children` — there were no rows to find because there was no
  table. It now fails on a `role="row"` wrapper for the right reason, with
  `aria-required-parent` alongside it.
- `Countdown`'s ring and digits match no axe rule at all. The case now
  mounts with an avatar, which renders an `<img>` and brings in `image-alt`
  and `nested-interactive`.
- `Advice` ran one rule. An `icon` sets `isLeading`, which wins the
  `v-else-if` and drops the avatar entirely, so the case now passes the
  avatar instead.

All three go red on a real regression: stripping `:alt` off the avatar image
in `Avatar.vue` fails `Advice` and `Countdown` on `image-alt`.

Also adds the `rounded` cases missed in `Input`, `InputNumber` and `Select` —
the prop is declared on all four of the affected components, changes markup,
and only `Textarea` had got a case for it.

Refs #63
All three are typed, documented and forwarded to the theme, and none of them
changes a single byte of rendered markup. Surfaced while closing the prop
coverage gap in #63 and measured by mounting each component with and without
the prop and diffing the HTML.

`Button.depth` already carried a deprecation note — spelled `@depricate`, so
no IDE, no `vue-tsc` and no docs generator ever saw it. The intent was real:
`docs/app/components/content/ComponentProps.vue` filters both `depth` and
`activeDepth` out of the props table by name, with a `@memo remove depricate
props` comment beside it. This spells the tag correctly and gives it a reason.

- `Button.depth`, `Button.activeDepth` — the `depth` compound variants in
  `src/theme/button.ts` are keyed on the legacy colour names (`default`,
  `danger`, `success`, `primary`, …), not on `air-*`. The default colour is
  `air-secondary-no-accent`, so both props are inert on it. Measured:
  `depth: 'dark'` changes the DOM on `color: 'primary'` and does not on the
  default.
- `Textarea.fixed` — works through `fixed` x `size` compound variants;
  `src/theme/input.ts` has five of them, `src/theme/textarea.ts` has none,
  because `Textarea` deliberately has no `size` (`// @memo we remove size`).

`fixed` is declared on ten components. Only `Textarea`'s is inert — the other
nine were probed the same way and all nine render. The tag goes on `Textarea`
alone.

Nothing is removed and no behaviour changes; both are 3.0.0 work. The
existing tests that exercise `depth` on legacy colours stay, so the behaviour
remains pinned until then.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
@IgorShevchik IgorShevchik changed the title test: cover the a11y and prop gaps from #63 refactor(Button,Textarea): deprecate three props that render nothing, and close the #63 test gaps Sep 2, 2026
…ions

Panel review pointed out that every pre-existing `@deprecated` block in this
repo pairs the prose with a separate `@removed 3.0.0` tag — see
`SidebarSection.vue:7-10` and the other nine `Sidebar*`/`Navbar*` components.
The three prop-level deprecations added here folded the removal version into
the prose only.

Nothing reads `@removed` today; this is house style, kept so a future tool
that keys off it finds every deprecation rather than most of them.

Checked before adding it: `ComponentPropsLinks.vue` filters `prop.tags` down
to `@link` and renders nothing otherwise, so the extra tag changes no docs
output.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc

Copy link
Copy Markdown
Collaborator Author

Review panel — five reviewers, run concurrently

Convened because the PR grew a public-API deprecation; a tests-only change would have needed /review alone.

Outcome: no blocking findings. Two items need a maintainer decision, both about visibility rather than correctness.

Verified independently

The QA reviewer re-ran every claim in the commit messages rather than reading them:

Claim Result
The four axe cases run real rules (3/3/3/5) Matches results.passes.length exactly
Each goes red on a real regression All three mutations reproduced: :alt off Avatar.vueimage-alt on Advice and Countdown; :label off the prompt buttons → button-name; role="row" on the TableWrapper root → aria-required-children and aria-required-parent
The Button override tests pin the active && guard Removing active && from both spreads fails both tests, in both the vue and nuxt projects
No new renderEach case duplicates a sibling indistinguishable-snapshots 22/22, zero new collisions

834/834 across the ten touched specs plus the guard.

The engineer reviewer confirmed the deprecation premise from the theme source and strengthened one claim: src/theme/textarea.ts:93 declares fixed: { false: '' } with no true branch at all, so the prop could not work even if Textarea had sizes. He also traced the theme graph to confirm the other nine fixed props are live — input-date, input-menu, input-tags, input-time and select inherit input.ts's five compound variants through defuFn, while input-number and pin-input carry their own — and checked the new snapshots actually drop md:text-(length:--ui-font-size-lg)/[normal] under fixed.

Security: nothing. The https://github.com/bitrix24.png avatar fixture is an existing convention in ~20 specs and is never dereferenced (neither the nuxt nor the happy-dom environment loads resources); the snapshots carry no links or secrets; the only v-html in src/runtime/components/ is CommandPalette.vue, pre-existing, untouched, already carrying its own sanitisation warning.

Acted on

  • Added @removed 3.0.0 to all three deprecation blocks (b4d8533c). Every pre-existing @deprecated block in this repo pairs the prose with that tag — SidebarSection.vue:7-10 and the nine other Sidebar*/Navbar* components — and these three had folded the version into the prose only. Checked first that ComponentPropsLinks.vue:11 filters prop.tags to @link, so the extra tag changes no rendered output.
  • Corrected the wording of the axe table in the description: those figures are rules passed. Three of the four cases additionally report one incomplete rule (color-contrast), which happy-dom cannot evaluate without real layout.

Open for the maintainer — 1: the deprecation is invisible on the docs site

Found independently by the documentation and engineer reviewers. Nothing under docs/app or docs/server reads the @deprecated tag — zero grep hits. depth and activeDepth happen to be hidden anyway, by a hardcoded name list in two places (docs/app/components/content/ComponentProps.vue:75 and docs/server/utils/transformMDC.ts:204), but Textarea.fixed is in neither. It will keep appearing on the Textarea docs page as an ordinary unmarked prop while its JSDoc says "Does nothing".

Adding fixed to those lists is not the fix: they are flat prop-name lists with no component scoping, so it would also disappear from Input, Select, InputNumber and the six others where it works.

Teaching the props table to render @deprecated is the fix, and the plumbing carries the tag: vue-component-meta's getJsDocTags (lib/schemaResolvers.js:43) passes every JSDoc tag through unfiltered, and compactProp (docs/server/utils/componentMeta.ts:54) strips only defaultValue. It would also let both hardcoded lists retire. Not done here: it changes the published docs for every component, and docs/.nuxt/component-meta.mjs is generated at docs build time, so it could not be verified in this environment — only the plumbing was checked, not the rendered result.

Open for the maintainer — 2: no paper trail for the 242 uncovered props

The CTO's one ask. The scan that found them was a one-off script, run by hand and discarded — deliberately, to avoid standing machinery. With a single maintainer, the concern is that the finding leaves with the session.

The numbers and the method are recorded in this PR body and in comments in the touched specs, so it is not lost outright. Whether that is enough, or whether it wants a line in #75 (the sync-pipeline tracker, where "an incomplete port shows up as a prop that exists in the types with no behaviour" already belongs), is a maintainer call.

Noted, not acted on

  • docs/content/docs/3.composables/use-confetti.md:86 uses depth="dark". Checked: not broken — color="link" is a legacy colour and src/theme/button.ts:337-348 has real depth × link compound variants, so it still does something. Worth revisiting before 3.0.0.
  • The @memo remove depricate props comments carry the same typo this PR fixes, in both filter locations. Outside the diff.
  • No no-deprecated ESLint rule is configured, so no CI job starts failing on internal uses of the newly tagged props.
  • The four axe cases are narrow by construction — each exercises the one prop combination that makes some rule fire. They do not speak for other configurations of the same components.

Generated by Claude Code

… by name

Nothing under `docs/app` or `docs/server` read the `@deprecated` tag — zero
grep hits before this. The two props that carried a deprecation were removed
from the output by a hardcoded name list in two places instead:

- `docs/app/components/content/ComponentProps.vue`
- `docs/server/utils/transformMDC.ts` (`propItemHandler`)

That left `Textarea`'s `fixed` rendering as an ordinary prop while its JSDoc
said it does nothing, and it could not be fixed by extending the lists: they
match on prop name with no component scoping, so adding `fixed` would also
have hidden it from the nine components where it works.

Both paths now read the tag:

- **Props table** — a new `ComponentPropsDeprecated` component, built to
  mirror the existing `ComponentPropsLinks`. Renders a badge carrying the
  `@removed` version when there is one, and the `@deprecated` prose through
  `MDC` like any other description.
- **`/raw/` markdown**, which is what `llms.txt` serves — the JSDoc block now
  carries `@deprecated` and `@removed` lines, so a consumer reading the raw
  page learns a prop is on its way out instead of silently not seeing it.

Both hardcoded lists are gone. `depth` and `activeDepth` therefore reappear
in the docs, marked, rather than vanishing — which is the point: someone with
`depth="dark"` in their code needs somewhere to find out it is going away.

Verified rather than assumed:

- The tags survive the pipeline. Ran `vue-component-meta`'s `createChecker`
  over `Textarea.vue` and `Button.vue` directly: `props[].tags` carries both
  `deprecated` (full text, newlines intact) and `removed` (`3.0.0`) for all
  three props. `compactProp` drops only `defaultValue`, so nothing filters
  them out downstream.
- The emitted markdown is right. Ran the new `propItemHandler` block against
  those exact tag objects: multi-line `@deprecated` text indents its
  continuation lines, `@removed` follows it, and a prop with no deprecation
  emits exactly what it did before.

Not verified: the rendered docs page. The docs dev server does not start in
this environment — `@nuxtjs/mcp-toolkit` throws `completable is not defined`
from its own bundle, unrelated to this diff. `nuxt typecheck docs` and
`eslint` both pass over the changed files.

Refs #63

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc

Copy link
Copy Markdown
Collaborator Author

Both open items closed

1 — the deprecation is now visible in the docs (409bc498)

Nothing under docs/app or docs/server read the @deprecated tag. Both paths now do:

  • Props table — new ComponentPropsDeprecated.vue, built to mirror the existing ComponentPropsLinks.vue: a badge carrying the @removed version, and the @deprecated prose rendered through MDC like any other description.
  • /raw/ markdown — the served source for llms.txt — the emitted JSDoc block now carries @deprecated and @removed lines.

Both hardcoded ['depth', 'activeDepth'] lists are gone, so those two props reappear in the docs marked rather than vanishing. That is the intent: someone with depth="dark" in their code needs somewhere to learn it is going away. Extending the lists was never an option — they match on prop name with no component scoping, so adding fixed would have hidden it from the nine components where it works.

What I verified, and what I did not.

The earlier note said the plumbing was checked but the result was not. That is now measured. Ran vue-component-meta's createChecker directly over Textarea.vue and Button.vue:

### Textarea.vue :: fixed
  tags: [
    { "name": "deprecated", "text": "Does nothing. It works through `fixed` x `size` compound\nvariants, ..." },
    { "name": "removed",    "text": "3.0.0" }
  ]

Both tags arrive intact, newlines and all, for all three props. Then ran the new propItemHandler block against those exact tag objects:

  /**
   * Keep the mobile text size on all breakpoints. (Left for backward compatibility.)
   * @deprecated Does nothing. It works through `fixed` x `size` compound
   *   variants, and `Textarea` deliberately has no `size`, so no variant ever
   *   matches.
   * @removed 3.0.0
   */
  fixed?: boolean | undefined;

A prop with no deprecation emits byte-for-byte what it did before.

Not verified: the rendered page. The docs dev server does not start in this container — @nuxtjs/mcp-toolkit throws completable is not defined from its own bundle, which no part of this diff imports. nuxt typecheck docs and eslint both pass over the changed files, and the four docs-facing specs are green, but nobody has looked at the actual table. Worth a glance on the first docs deploy after merge.

2 — paper trail filed (#75)

Added as item 6 on the sync-pipeline tracker rather than as a new issue: it is the same failure mode item 2 is about — a port that arrives incomplete and passes every gate. Carries the 1140/242 measurement, the upstream comparison showing the uncovered props are disproportionately ours, the one-off script in full so it need not be reinvented, the caveat that an uncovered prop is not automatically a bug, and when re-running is worth it. P3.


Generated by Claude Code

@IgorShevchik
IgorShevchik merged commit 1da904d into main Sep 2, 2026
3 checks passed
@IgorShevchik
IgorShevchik deleted the claude/repo-rules-35um4e branch September 2, 2026 09:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants