Commit Graph

785 Commits

Author SHA1 Message Date
Sam Julien 224871e135 fix(shell-docs): move 'Choose your AI backend' heading into IntegrationGrid component 2026-04-23 08:34:37 -07:00
Sam Julien e36792d04b fix(shell-docs): hide IntegrationGrid on framework-scoped routes 2026-04-23 08:34:37 -07:00
Sam Julien 81dced2e8e docs(shell-docs): add bridging text between InlineDemo and gif on prebuilt component pages 2026-04-23 08:34:37 -07:00
Sam Julien 1ad171b620 docs(shell-docs): writing pass to remove em-dash overuse and fix hardcoded framework references
Replace em-dashes in prose across ~37 shell-docs files with appropriate
punctuation (colons, semicolons, commas, parens, periods). Also fixes a
hardcoded "LangGraph Python" reference in quickstart.mdx bridging text,
adds a user-friendly placeholder when no framework is selected on snippet
pages, and makes heading code font size proportional rather than fixed.
2026-04-23 08:34:37 -07:00
Sam Julien 824553b251 chore(showcase): update generated data and quickstart default integration
- Update registry.json, demo-content.json, status.json, constraints.json,
  docs-status.json across shell/shell-docs/shell-dojo
- Add integration="langgraph-python" default to quickstart InlineDemo so
  the base unscoped page shows a demo instead of being empty
2026-04-23 08:34:37 -07:00
Sam Julien b7090a5d07 feat(shell-docs): build real feature matrix, fix card underlines, add backend intro
- Replace FeatureMatrix stub with a real server-rendered table reading from
  registry — 17 integrations × 12 curated feature columns, sticky first column,
  ✓/— cells, integration names link to /{slug} landing pages
- Fix matrix links from /integrations/{slug} (404) to /{slug}
- Remove redundant "Feature comparison" section from index.mdx (FeatureMatrix
  was a stub pointing to same destination as IntegrationGrid)
- Add .reference-content .not-prose a rule to suppress underlines on card grids
  inside MDX without breaking prose link styling
- Add intro sentence to "Explore by AI backend" section
2026-04-23 08:34:37 -07:00
Sam Julien 9582d4770a fix(shell-docs): fix empty FeatureIntegrations and matrix 404
- Correct 3 mismatched feature IDs in MDX (generative-ui-tool-based ->
  gen-ui-tool-based, frontend-tools-sync -> frontend-tools, reasoning ->
  agentic-chat-reasoning) so FeatureIntegrations renders integration chips
- Remove stale 'matrix' from RESERVED_ROUTE_SLUGS (no app/matrix/ route exists)
- Replace broken /matrix links in IntegrationGrid and search-modal with /
  since the matrix lives in shell-dashboard, not shell-docs
2026-04-23 08:34:37 -07:00
Sam Julien 4873761c2e Merge branch 'main' into docs-sync/needs-review/189c45fb4-1776791837 2026-04-22 19:04:59 -07:00
Jordan Ritter 8db7b211a4 fix(shell-docs): resolve findFrameworksWithCell + SidebarLink scope type errors
Two pre-existing type errors from commit 9b05ed41 surfaced on main's
Docker build:

1. `unscoped-docs-page.tsx` imports `findFrameworksWithCell` from
   `@/lib/docs-render`, but the helper was only declared locally in the
   two page.tsx routes with a 1-arg signature (and referenced an
   undeclared `demos` in one case — dead code). Export a 3-arg shared
   version from docs-render.tsx that accepts the integration slug list
   and demo map as parameters (keeps the lib free of registry imports),
   drop the dead local in `[[...slug]]/page.tsx`, and rewire the live
   caller in `[framework]/[[...slug]]/page.tsx` through the shared
   export.

2. The Step-2 section cards on the overview call `<SidebarLink>`
   without the required `scope` prop. The prop was already ignored
   internally (destructured as `_scope`) so relaxing it to optional is
   the minimal fix and keeps the call-site intent documented.

`npm run build` in showcase/shell-docs now compiles cleanly.
2026-04-22 12:16:38 -07:00
Sam Julien 1d1ed63a6b Merge remote-tracking branch 'origin/docs-sync/needs-review/189c45fb4-1776791837' into docs-sync/needs-review/189c45fb4-1776791837 2026-04-22 11:23:14 -07:00
Sam Julien 8e2c4c3488 Merge remote-tracking branch 'origin/main' into docs-sync/needs-review/189c45fb4-1776791837
# Conflicts:
#	showcase/shell-docs/src/content/docs/learn/index.mdx
2026-04-22 11:12:48 -07:00
Jordan Ritter 9b05ed41b3 feat(showcase/shell-docs): error boundary consolidation + docs components
Drop error-boundary-card in favour of Next.js error.tsx at each route,
refresh docs components (brand-nav, docs-callout, docs-page-view,
docs-steps, docs-tabs, framework-provider/selector/tabs,
property-reference, router-pivot, sidebar-link, snippet), update
docs-render + mdx-registry + reference-items for the new QA shape.
2026-04-22 11:00:46 -07:00
github-actions[bot] e713ad2a07 style: auto-fix formatting 2026-04-22 11:20:02 +00:00
Alem Tuzlak 06d24fd8ba Merge remote-tracking branch 'origin/main' into fix/scrub-open-gen-ui
The scrub and #4084 touched the same surface: #4084 re-added an `open:`
generative_ui profile listing `open-gen-ui`/`open-gen-ui-advanced`, and
re-added both features to `constrained-explicit.allowed`. Extending the
branch's scrub to both re-additions keeps the semantic consistent with
the schema (which already dropped `open` from the approaches enum).

- `showcase/shared/constraints.yaml`: drop `open-gen-ui` +
  `open-gen-ui-advanced` from `constrained-explicit.allowed`; drop main's
  re-added `open:` profile entirely.
- `showcase/packages/langgraph-python/manifest.yaml`: drop the now-orphan
  `open-gen-ui` + `open-gen-ui-advanced` feature and demo entries
  (validator confirmed they had no allowed approach left).
- Regenerated `showcase/shell/src/data/registry.json` + sibling
  `shell-docs`/`shell-dojo` registries and `constraints.json` via
  `pnpm --dir showcase/scripts generate-registry`. All 17 integrations
  validate.

`feature-registry.json` intentionally still defines both features — the
original scrub commits (2b996c54d, 27f886e59) left it untouched, so the
demo source files on disk also stay. Follow-up deletion if desired is
out of scope for this merge.
2026-04-22 13:17:34 +02:00
Sam Julien 8c4d0c36f9 fix(shell-docs): remove stale 'integrations' from RESERVED_ROUTE_SLUGS
There is no app/integrations/ route, so the reservation was causing
/integrations/... URLs to 404. Without it, these paths fall through to
UnscopedDocsPage via the non-integration fallthrough in [framework].
2026-04-21 17:35:01 -07:00
Sam Julien b37a3043e6 fix(shell-docs): remove hardcoded langgraph-python from main docs MDX
Strip snippet_framework: langgraph-python from frontmatter and
integration="langgraph-python" from all InlineDemo tags in the
main docs tree (27 files). On framework-scoped pages frameworkOverride
drives Snippet and InlineDemo; on unscoped pages FrameworkGuardedContent
already hides the body until a framework is selected, so no default
is needed.
2026-04-21 17:35:01 -07:00
github-actions[bot] a043aa5ba0 style: auto-fix formatting 2026-04-21 17:35:01 -07:00
Sam Julien a265cc7d48 fix(shell-docs): skip root-flagged dirs from parent nav tree
buildNavTree now checks meta.root before including a subdirectory,
so unselected/ (and any other root:true directory) is excluded from
the main nav tree. This eliminates the flicker where SidebarLink
generated /langgraph-python/unselected/coding-agents and the
[framework] route had to server-redirect to the correct scoped URL.
2026-04-21 17:35:01 -07:00
Sam Julien 64aa05d1b8 fix(showcase/shell-docs): rewrite MDX body links to framework-scoped URLs
On framework-scoped pages, MDX links like /quickstart rendered as plain
<a href="/quickstart"> causing RouterPivot redirect flicker. Override the
MDX `a` component when frameworkOverride is set to prepend the framework
prefix to root-relative internal links.
2026-04-21 17:35:01 -07:00
Sam Julien 87fb9e8260 fix(showcase/shell-docs): fix /<slug> 404 via UnscopedDocsPage fallthrough
Next.js routes /quickstart to [framework]/[[...slug]] (dynamic segment
beats optional catch-all), where "quickstart" is not a registered
integration, causing notFound(). Fix by:

- Extracting the unscoped doc rendering logic into UnscopedDocsPage
- Falling through to it in [framework] when the slug is not a framework
- Simplifying [[...slug]]/page.tsx to handle only the root overview
2026-04-21 17:35:01 -07:00
Sam Julien bb0b14702c fix(showcase/shell-docs): eliminate URL flicker on unscoped navigation
SidebarLink now uses storedFramework as fallback so links on the
overview page go directly to /<framework>/<slug> without a RouterPivot
redirect. OverviewNavItem and section cards now use SidebarLink for the
same reason. FrameworkSelector "Clear selection" was navigating to
/docs/<slug> (broken); fixed to /<slug>. hrefFor now preserves the
current slug when switching frameworks from an unscoped page.
2026-04-21 17:35:01 -07:00
github-actions[bot] 5e7e1be672 style: auto-fix formatting 2026-04-21 17:35:01 -07:00
Sam Julien 3218c54cc1 fix(showcase/shell-docs): remove remaining /docs/ hardcoded hrefs
SidebarLink fallback, framework-scoped backLink, "framework-agnostic
version" banner link, FrameworkLandingPage sidebar, and brand-nav
all still pointed at /docs/* which routes to 404 via the [framework]
catch-all. Switch all to / or /<slug>.
2026-04-21 17:35:01 -07:00
Sam Julien 671ecd1091 fix(showcase/shell-docs): make InlineDemo framework-aware via frameworkOverride
Override InlineDemo in DocsPageView's MDX component map to substitute
defaultFramework for the hardcoded integration prop when a framework
is selected. MDX files don't need to change — the override happens at
the render layer, matching how Snippet already handles this.
2026-04-21 17:35:01 -07:00
Sam Julien 0057d6beb4 fix(showcase/shell-docs): fix broken /docs/* route links in root page
DOCS_SECTIONS, OverviewNavItem, CopilotKit Docs link, backLink, and
slugHrefPrefix all generated /docs/<slug> paths that 404 — the
[framework] catch-all intercepted "docs" as a framework slug and
returned notFound(). Strip the /docs prefix so all root-route links
resolve correctly.
2026-04-21 17:35:01 -07:00
Sam Julien c730330d0d docs(shell-docs): content audit — fix broken snippets, links, and syntax
Page-by-page audit of showcase/shell-docs MDX content. All changes are
in src/content/docs/.

## Broken snippet region fixed
- generative-ui/a2ui/dynamic-schema.mdx: Step 5 referenced
  `runtime-inject-tool` which does not exist in the declarative-gen-ui
  cell. Replaced with a hardcoded code block showing `injectA2UITool: true`
  (same content already shown on the parent a2ui.mdx page).

## MDX syntax fix
- frontend-actions.mdx: stray closing ``` at end of file (would cause
  a parse/render failure).

## Internal link fixes — /docs/ prefix removed (×14 files)
The docs app routing does not use a /docs/ prefix — pages live at
/<slug>. Links using /docs/<slug> hit the reserved-slug guard in the
[framework] route and 404. Fixed across:
  generative-ui/index.mdx (7 links)
  generative-ui/tool-based.mdx (3 links)
  learn/index.mdx (6 links)
  multi-agent/subagents.mdx (2 links)
  shared-state.mdx (2 links)
  shared-state/streaming.mdx (2 links)
  shared-state/agent-readonly.mdx (4 links)
  troubleshooting/debug-mode.mdx
  troubleshooting/error-debugging.mdx
  troubleshooting/migrate-to-1.10.X.mdx
  troubleshooting/migrate-to-1.8.2.mdx (2 links)
  troubleshooting/observability-connectors.mdx

## Internal link fixes — /unselected/ removed (×2 files)
  backend/copilot-runtime.mdx
  backend/custom-agent.mdx
2026-04-21 17:35:01 -07:00
Jordan Ritter 8e6991cea1 Fix showcase dashboard links and dojo langgraph column (#4127)
## Summary

- **shell-dashboard:** dashboard.showcase.copilotkit.ai rendered every
"demo" and "code" link as `http://localhost:3000/...`. Root cause:
`NEXT_PUBLIC_SHELL_URL` was never provided at build time and the source
fell back to `localhost:3000`. Next.js inlines `NEXT_PUBLIC_*` at `next
build`, so a runtime Railway env var could not rescue a bad build. Fix
plumbs the value through as a Docker build arg from
`showcase_deploy.yml` and fails loudly at build if it's unset so this
can't regress silently.
- **shell-dojo:** dojo.showcase.copilotkit.ai was missing items in the
langgraph column (langgraph-python showed 9 demos vs 20+ in the
manifests). Root cause: `shell-dojo/src/data/registry.json` was stale —
the generator only wrote to `shell/`, the dojo Dockerfile never ran the
generator at build, and the CI path filter didn't rebuild the dojo when
manifests changed. Fix dual-emits from `generate-registry.ts` to
`shell/`, `shell-dojo/`, and `shell-docs/`, runs the generator in the
dojo Dockerfile, expands the workflow's path filter to include
`packages/**` and `shared/**`, and refreshes the committed JSON so it
matches what the generator produces today. Langgraph-python demo count 9
→ 32.

## Test plan

- [x] `shell-dashboard` Docker build succeeds with
`NEXT_PUBLIC_SHELL_URL` build arg (Depot `36wlvzkgp1`).
- [x] `shell-dashboard` Docker build fails loudly when the build arg is
omitted (Depot `mbh41c3qtk`).
- [x] `shell-dojo` Docker build succeeds; generator+bundler run at
build; 159 demos bundled (Depot `h7bbq8f8jt`).
- [x] `showcase_deploy.yml` passes YAML validation.
- [ ] After merge + deploy: verify `dashboard.showcase.copilotkit.ai`
links point to `https://showcase.copilotkit.ai/...`.
- [ ] After merge + deploy: verify `dojo.showcase.copilotkit.ai` shows
the full langgraph column (langgraph-python ≥ 20 items).
2026-04-21 15:27:13 -07:00
Martha Schumann bb0a9191bb docs(mastra): simplify AG-UI context access in Agent instructions example
Drops the inline TypeScript typecast from the Mastra agent-app-context
example and uses optional chaining + direct access instead, so the doc
snippet is easier to read and copy. Keeps optional chaining on `.find`
so the example stays safe when the AG-UI context is absent. Also fixes
the `[!code highlight:N]` count after the comment line was removed.

Ports @Abubakar-01's changes from #4125 so they can ship together with
the `requestContext` rename, targeting the new `showcase/shell-docs/`
path after the shell restructure on main.

Co-authored-by: Muhammad Abubakar <abubakaran102025@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:44:58 -07:00
Martha Schumann bcd5a92d32 Merge remote-tracking branch 'origin/main' into fix/restore-mastra-readables-content 2026-04-21 13:16:01 -07:00
github-actions[bot] d0e99e66be style: auto-fix formatting 2026-04-21 20:13:15 +00:00
Jordan Ritter e2a6cc2bfe Regenerate shell-dojo registry at build and expand CI trigger paths
The dojo app was missing items under the langgraph column because
shell-dojo shipped a stale committed registry.json. The generator
only wrote to shell/, the dojo Dockerfile didn't run the generator
at build, and the CI path filter didn't rebuild the dojo when
manifest files changed.

Fix: emit from generate-registry.ts to shell, shell-dojo, and
shell-docs; add the generator step to shell-dojo's Dockerfile;
expand the deploy workflow's path filter to include packages/**
and shared/**; and refresh the committed registry/demo-content
JSON so files on disk match what the generator produces today.
2026-04-21 13:10:52 -07:00
github-actions[bot] 82f3a7d9bd style: auto-fix formatting 2026-04-21 19:30:23 +00:00
Sam Julien 217ad734c8 fix(showcase/shell-docs): wire up threads + self-hosting from docs sync
The upstream docs sync added 24 new integration pages (`threads.mdx`,
`premium/self-hosting.mdx`) plus learn/reference content, but didn't
land the runtime wiring they depend on — so the pages would ship blank.
It also accepted upstream changes in tool-rendering.mdx over local
modifications that needed to be restored.

- Register `Threads` / `SelfHosting` in SNIPPET_MAP so the shared
  `<Threads />` and `<SelfHosting />` tags inline on integration pages
- Register `ThreadsEarlyAccess` wrapper + `MessageSquareMore` /
  `Network` / `Newspaper` icons in mdx-registry for the new threads
  content and the rebuilt `learn/index` card grid
- Revert tool-rendering.mdx upstream-wins regressions: framework-neutral
  `/unselected/server-tools` link and `components={props.components}`
  forwarding for the `<SharedContent>` override pathway
- Add `threads` + `...premium` to every integration's root meta.json
  plus 11 new `premium/meta.json` files so the new pages appear in the
  sidebar; update `docs/meta.json`, `docs/learn/meta.json`, and
  `docs/premium/meta.json` the same way
- Fix `convertMarkdownTableToHtml` to emit JSX-valid tags. It was
  generating `style="..."` string attributes, which next-mdx-remote
  rejects; this path was dormant until the new threads page put a
  markdown table inside a `<Step>`
2026-04-21 12:21:36 -07:00
copilotkit-devops-bot[bot] c3867ff6cd chore: docs sync from main — needs review (2026-04-21) 2026-04-21 17:17:17 +00:00
Jordan Ritter 4e3a23199d chore(showcase): regenerate demo-content bundles
Regenerate after the bundler fix so the committed bundle reflects
the multi-file contributor tracking and endLine extension behavior.
2026-04-20 22:21:14 -07:00
Jordan Ritter bfe0ff1e7f fix(shell-docs/reference-items): collapse index.mdx to parent slug with flat-file collision guard
Directory-plus-index.mdx layout produced two reference entries for
the same logical page: one at `foo/` (the index) and one at `foo`
(a flat sibling if it existed). Collapse index.mdx into the parent
slug so the generated list has a single canonical entry, and bail
out with a clear error when a flat-file collision would shadow the
index. Prevents silently dropping one of the two pages at build
time.
2026-04-20 22:21:03 -07:00
Jordan Ritter 272deca9d5 fix(shell-docs/error-boundary): stable effect deps via error.message and error.digest
The log effect depended on the error object identity, which changes
on every render even when the underlying error is the same — so the
effect fired repeatedly and spammed the log. Depend on
error.message and error.digest (primitive, stable across renders
of the same error) instead. React's exhaustive-deps check is still
satisfied because those are the fields the effect actually reads.
2026-04-20 22:20:49 -07:00
Jordan Ritter e84f1f34cd fix(shell-docs): route-level content handling and navigation correctness
A cluster of UX correctness fixes across the page handlers and
the shared brand nav:

- Filter out undeployed frameworks before rendering so the route
  doesn't produce blank pages that users can reach via stale links.
- Strip the leading body H1 with a CRLF-safe regex that only matches
  when the body H1 equals the frontmatter title — mirrors ag-ui
  route behavior so two stacked titles never render.
- Reference routes now titleCase the slug and resolve via the
  index.mdx fallback, matching the directory-plus-index layout the
  docs source uses.
- ag-ui title resolver gains a fallback so deep slugs without a
  matching registry entry still produce a reasonable title instead
  of crashing.
- brand-nav builds the mobile link href dynamically so it points at
  the current framework rather than a hard-coded placeholder.
2026-04-20 22:20:44 -07:00
Jordan Ritter a609132295 fix(shell-docs/framework-selector): disable undeployed option buttons in dropdown
The selector dropdown previously rendered every framework entry as
a clickable option, including ones that had been marked as not
deployed. Selecting an undeployed entry routed to a blank page.
Disable the button for those entries so the dropdown matches the
surrounding tab behavior, which already hides them.
2026-04-20 22:20:30 -07:00
Jordan Ritter 2dc2da4eb2 fix(shell-docs/framework-provider): validate stored framework on mount and cross-tab storage events
localStorage can hold a value from a previous deploy that no longer
exists in the current frameworks list (package renames, undeploy,
etc.), which pins the provider to a bogus framework identity until
the user manually picks another. Validate the stored value against
the current list both at mount and on cross-tab `storage` events,
and fall back to the default when it doesn't match.
2026-04-20 22:20:25 -07:00
Jordan Ritter 206ec9e6bc fix(shell-docs/framework-tabs): guard count mismatch, resync on frameworks prop change, drop unused props
Framework-tabs assumed the items array always matched the frameworks
prop one-to-one. A count mismatch wedged the active index at a stale
value that could fall outside the new frameworks array, rendering a
blank tab. Add a length-mismatch guard that re-syncs state when the
frameworks prop changes between renders, and remove props that were
threaded through but never read so the surface matches what the
component actually uses.
2026-04-20 22:20:19 -07:00
Jordan Ritter 08c37be7a8 fix(shell-docs/docs-tabs): use positional findIndex for duplicate or mismatched item sets
When the tab item array contains duplicate values or has a length
that doesn't match the items prop, looking up the active index by
value conflates tabs. Find the active tab by position instead so
each rendered tab has a stable identity regardless of duplicated
or drifted values.
2026-04-20 22:20:10 -07:00
Jordan Ritter 0845effb00 fix(shell-docs/mdx-registry): merge caller style on img and video overrides
The img and video overrides spread props, then replaced style wholesale
with the layout defaults — silently discarding any author-provided
style keys from MDX. Merge author style first and layout defaults
last so we preserve author intent (e.g. custom max-width, filters)
while still enforcing our rounded-corner + marginBottom guards.
2026-04-20 22:20:04 -07:00
Jordan Ritter d8eaebc2b4 fix(shell-docs/mdx-registry): drop allow-same-origin from iframe sandboxes and validate InlineDemo src
Per MDN, combining `allow-scripts` with `allow-same-origin` lets the
framed page remove its own sandbox attribute at runtime — that is a
sandbox escape regardless of how much we trust the origin. Drop
`allow-same-origin` from all three iframe sandboxes (InlineDemo,
author-supplied IFrame, YouTube embed). None of them need same-origin
semantics with the parent docs host to function.

Also validate InlineDemo's computed demo URL at the sink instead of
trusting the registry blindly — a malformed backend_url should render
a visible error placeholder, not a silently broken iframe.
2026-04-20 22:19:50 -07:00
Jordan Ritter 24dbeb29c1 fix(shell-docs/mdx-registry): reject javascript/data/vbscript hrefs via scheme allowlist
MDX-authored hrefs flow into <a> and <Link> without scheme filtering.
`rel="noopener noreferrer"` does not neutralize script-URL schemes
like `javascript:`, `data:text/html`, or `vbscript:`, so a malicious
snippet could land in the rendered page as an XSS vector.

Add sanitizeHref() with an allowlist of http/https/mailto/tel plus
relative / protocol-relative / fragment / query forms. Anything else
returns null and the A/Link overrides render a <span> with the same
visible content instead of an anchor. Also add a protocol-relative
(`//`) early-return in isExternalHref so those URLs correctly route
through a plain <a> rather than next/link.
2026-04-20 22:19:17 -07:00
Jordan Ritter b3f4f248a2 fix(shell-docs): parse H1 fallback from post-frontmatter body and strip only on match
The title resolution path had two correctness bugs:

- readTitle and loadDoc both ran the H1 fallback regex against the
  raw file, so a YAML comment like `# ...` inside frontmatter could
  be picked up as the page's H1. Run the regex against the parsed
  body (frontmatter stripped) instead. Also log a console.error when
  frontmatter parsing blows up so a malformed file doesn't silently
  yield a garbage title.
- docs-page-view unconditionally stripped the leading body H1, which
  dropped distinct H1 headings whenever the MDX body didn't match
  the frontmatter title. Mirror the ag-ui route: only strip when the
  body H1 equals the FM title after whitespace normalization, and
  use `\r?\n` so CRLF-authored MDX parses correctly too.
2026-04-20 22:18:33 -07:00
Jordan Ritter 2a2bcb2209 fix(shell-docs/docs-render): match doubled-brace components prop in inlineSnippets
MDX authors pass component-map overrides via doubled-brace object
syntax, e.g. `<SharedContent components={{ Foo: Bar }} />`. The
previous regex used `[^}]*` which truncates at the inner `}`, so
the tag never matched and the snippet was never inlined. Match the
doubled-brace object form explicitly with `\{\{...\}\}` and
`[\s\S]*?` so multi-line prop objects still match.
2026-04-20 22:18:14 -07:00
Jordan Ritter f1be2bc0d3 fix(shell-docs/docs-render): backref and longest-first alternation in convertTablesInJSX
JS regex alternation is leftmost-first, not leftmost-longest, so for
source like `<Tabs>` the pattern `Tab|Tabs` matches "Tab", `[^>]*`
consumes the "s", and the close-side alternation would then pair
with any container's `</...>` regardless of which tag opened. Two
separate bugs fell out of this:

- Prefix collisions (Tab vs Tabs) silently skipped table conversion.
  Sort JSX_CONTAINER_TAGS longest-first so the opener always matches
  the actual outer tag name.
- Mismatched pairs like `<Tabs><Tab>x</Tab></Tabs>` paired the outer
  `<Tabs>` with the inner `</Tab>`, stranding `</Tabs>`. Use a
  numbered backref (`\\2`) on the closing tag so only the same tag
  name can close the match.

Also tighten the inline comment on the nested-same-tag bailout to
reflect that the non-greedy match now closes on the same tag, not
"any container in the set".
2026-04-20 22:18:00 -07:00
Jordan Ritter 235f6a67a6 Merge jpr5/shell-docs-td-routes-infra into tech-debt branch 2026-04-20 19:44:57 -07:00
Jordan Ritter 4b2ef609bb Merge jpr5/shell-docs-td-lib into tech-debt branch 2026-04-20 19:44:57 -07:00