Fix preview rendering and inline text editing in email builder#5
Merged
Conversation
690c1d2 to
180a813
Compare
180a813 to
21a3d15
Compare
added 2 commits
June 9, 2026 11:40
The shared wrapper's `@media (prefers-color-scheme: dark)` block made preview text light-grey on the forced-white block background under a dark OS theme. Strip that block from preview output only (JS previews before `srcdoc`; server-rendered template preview via `stripDarkModeCSS`). Sent emails are unaffected.
Inline editing was blocked for elements with a non-text child, so text
sharing a `<p>` with an icon or link wasn't editable.
- `replaceTextVars` now rewrites placeholders only in text content, so
`href="{{.Var}}"` is no longer corrupted (neutralized to `#` via
`replaceHrefVars`).
- `<img>`/`<a>` no longer block editing: surrounding text is wrapped in
editable spans, link text is edited separately. Listener wiring moved
to `bindEditable`.
21a3d15 to
31eb13c
Compare
There was a problem hiding this comment.
Pull request overview
This PR targets two UX issues in the Sendry email builder preview/editor: dark-mode CSS leaking into iframe previews (making forced-light previews unreadable) and inline text editing being blocked when text is adjacent to non-text children like icons/links.
Changes:
- Strip
@media (prefers-color-scheme: dark)CSS from preview output (client-side preview iframes and server-rendered template preview). - Update builder placeholder rewriting to avoid modifying variables inside HTML tags/attributes, and neutralize
href="{{.Var}}"placeholders. - Adjust inline-edit enabling to allow editing text nodes in mixed-content elements by wrapping text fragments in editable spans and refactoring edit binding logic.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| internal/web/views/template_view.html | Strips dark-mode media block from rendered template preview before setting iframe.srcdoc. |
| internal/web/views/block_view.html | Strips dark-mode media block from block preview iframe HTML. |
| internal/web/views/block_form.html | Strips dark-mode media block from block form live preview iframe HTML. |
| internal/web/static/js/builder.js | Updates variable placeholder rewriting and expands inline-edit support for mixed-content nodes (icon/link + text). |
| internal/web/handlers/templates.go | Adds server-side stripDarkModeCSS for template preview output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
indexOf(original) hit the first match, so editing a repeated short fragment rewrote the wrong one. Record each fragment's source offset at wrap time and apply edits by offset; fall back to indexOf if it drifts.
919633a to
5e1958c
Compare
The same @media (prefers-color-scheme: dark) stripping one-liner was duplicated in template_view.html, block_view.html and block_form.html. Move it to a shared preview-utils.js exposing SendryPreview.stripWrapperDarkModeCSS so future changes to the wrapper CSS require editing one place instead of three.
Add TestStripDarkModeCSS asserting that the wrapper's dark-mode block (identified by .force-page-bg) is removed while custom dark-mode CSS without that marker is preserved, along with a no-op case.
Owner
|
@copilot all inline review comments have been addressed and threads resolved. Two new commits on the branch:
Please re-review. |
…ibute Prevents replaceHrefVars from rewriting longer attributes such as data-href or xlink:href by requiring a whitespace boundary before href.
- enableInlineEdit: skip nodes whose ancestor is already contenteditable so <a> inside <td> does not create nested edit zones that break source-index mapping in saveInlineEdit - template_view / block_view / block_form: defer initial render() until DOMContentLoaded so SendryPreview helper is loaded before use
Previously the regex only matched flat placeholders like {{.Name}}.
Sendry templates allow nested fields (e.g. {{.User.Email}}), which
were left as raw template syntax in the builder preview instead of
being wrapped in a styled placeholder span. Extend the regex to
accept dotted paths and optional whitespace inside braces.
Owner
|
@copilot review |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent fixes in the email builder (sendry-web). Atomic commits.
1. Preview showed grey text in dark mode
The shared email wrapper carries a
@media (prefers-color-scheme: dark)block. Previews render it in an iframe, so under a dark OS theme the text became light-grey on the forced-white block background — unreadable.Fix: strip the dark-mode block from preview output only (JS previews before
srcdoc; server-rendered template preview viastripDarkModeCSS). Sent emails keep dark mode.2. Text next to an icon/link was not editable
Inline editing was disabled for any element with a non-text child, so status text sharing a
<p>with an icon (Оплачен <img>) or a link wasn't editable.Fix:
replaceTextVarsnow rewrites placeholders only in text content (no longer breakshref="{{.Var}}", which is neutralized to#viareplaceHrefVars);<img>/<a>no longer block editing — surrounding text is wrapped in editable spans, link text is edited separately.