Skip to content

fix(canvas): render base.text tag:none as bare text to match published DOM#63

Merged
DavidBabinec merged 2 commits into
mainfrom
fix/canvas-text-tag-none-bare-text
Jun 16, 2026
Merged

fix(canvas): render base.text tag:none as bare text to match published DOM#63
DavidBabinec merged 2 commits into
mainfrom
fix/canvas-text-tag-none-bare-text

Conversation

@DavidBabinec

Copy link
Copy Markdown
Contributor

What

In the visual editor canvas, a base.text node with tag: none was wrapped in a <span>. The publisher renders tag: none as bare text with no element (src/modules/base/text/index.ts{ html: text }). That divergence let descendant selectors match the phantom span in the builder while leaving the published page untouched.

Concretely, on the 404 template the number is one .ist-404__num container with three base.text children — two tag: none 4s and a tag: span 0 — plus an ambient rule .ist-404__num span { color: var(--ist-accent) }. In the canvas all three were spans, so the rule painted the 4s orange; on the published page the 4s are bare text, so they stayed black. The builder lied about the result.

Fix

The canvas now renders tag: none as bare text + <br> breaks (a fragment, no host element), exactly like the publisher — so the canvas DOM equals the published DOM. This is the same canvas-equals-published principle that drove removing the per-node wrapper <div>.

  • TextEditor.tsx: tag: none display path renders a BareText fragment instead of a <span> wrapper. The inline-edit branch still hosts a <span> for an active session (unreachable from the canvas for tag: none — there is no element to double-click).

Trade-off (intentional, agreed with author)

A tag: none node owns no element, so it has no in-canvas selection ring / hover / inline-edit — it is selected via the Layers panel and edited via the Properties → Text field. This is the honest reflection of "no element": that text has no box on the published page either. A future, separate PR could add Range-based selection to restore direct manipulation without a phantom element.

User/developer impact

  • Users: the builder now shows the same text colors (and any other descendant-selector styling) as the published site for tag: none text.
  • Developers: canvas/publish DOM parity holds for tag: none.

Verification

  • bun run build
  • bun run lint
  • bun test ✓ — 5437 pass, 0 fail (added 3 canvas-render tests in base-modules.test.ts)
  • Live in the editor (isolated dev server against a DB containing the 404 template): the 4s render black and the 0 orange, matching the front end. .ist-404__num DOM is 4<span data-node-id=…>0</span>4 (childNodes ["#text:4","SPAN","#text:4"]), no console errors.

Note: the pre-push hook flags a react-doctor/no-danger warning on the non-none display path's dangerouslySetInnerHTML — that is the pre-existing escaped-text + <br> pattern already on main (only relocated by this diff), not a new regression.

🤖 Generated with Claude Code

DavidBabinec and others added 2 commits June 15, 2026 12:15
…d DOM

A `base.text` node with `tag: none` publishes as bare text (no element) but
the canvas wrapped it in a `<span>`. Descendant selectors such as
`.ist-404__num span` then matched the phantom span in the editor while leaving
the published page untouched — e.g. the 404 template's two `tag: none` "4"s
rendered orange in the builder but black on the published page.

The canvas now renders `tag: none` as bare text + `<br>` breaks, exactly like
the publisher (`src/modules/base/text/index.ts`), so the canvas DOM equals the
published DOM. This is the same canvas-equals-published principle that drove
removing the per-node wrapper `<div>`.

Trade-off: a `tag: none` node owns no element, so it has no in-canvas selection
ring / hover / inline-edit; it is selected via the Layers panel and edited via
the Properties "Text" field. The inline-edit branch still hosts a `<span>` for
an active session, which is unreachable from the canvas for `tag: none` (no
element to double-click).

Verified live in the editor: the 404 template's "4"s now render black and the
"0" orange, matching the front end; `.ist-404__num` DOM is `4<span>0</span>4`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Satisfies react-doctor/no-render-in-render: a named component returning a
fragment replaces the inline render helper. Still adds no host element, so the
tag:none canvas DOM remains bare text matching the published page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@DavidBabinec DavidBabinec marked this pull request as ready for review June 16, 2026 16:33
@DavidBabinec DavidBabinec merged commit 1a762ec into main Jun 16, 2026
6 checks passed
@DavidBabinec DavidBabinec deleted the fix/canvas-text-tag-none-bare-text branch June 16, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant