feat(automations): highlight {{ }} tokens + flag typos in builder text fields (#3653)#3727
Conversation
…t fields (#3653) Second of the two post-#3721 follow-ups. Token-bearing text/textarea fields (catalog `tokens: true`: message text/DM-to, notify title/body, condition values, setVar value) now use TokenTextField — a highlight backdrop renders `{{ trigger.* }}` / `{{ var.* }}` tokens blue when recognized and red+wavy when not, with unrecognized tokens listed inline below the field to catch typos like `{{ trigger.lastestVersion }}` or a `var.` name with no matching variable. - tokenHints.ts (pure, tested): validTokenSet(triggerType, vars) from the exported TRIGGER_TOKENS + UNIVERSAL_TOKENS + known variables; tokenize() and unknownTokens(). - Non-blocking hint (not a hard save gate) to avoid false positives on tokens the static registry might not enumerate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VBLhGGNh35oMwTL53va1Y5
|
Claude finished @Yeraze's task —— View job PR Review: feat(automations): highlight {{ }} tokens + flag typos in builder text fields
Overall this is a clean, well-scoped implementation. The layered backdrop/transparent-input technique is a well-known approach for this kind of rich-text-without-a-rich-editor use case. A few observations:
|
| Area | Status |
|---|---|
Core logic (tokenHints.ts) |
✅ Correct and clean |
UI component (TokenTextField.tsx) |
✅ Good; minor scroll-sync and zero-width space doc nits |
Tests (tokenHints.test.ts) |
✅ Covers main cases; a few edge cases missing |
| Catalog integration | ✅ Clean tokens: true annotation approach |
| CSS | ✅ Solid; layered backdrop technique well-executed |
| Performance | ✅ Correctly useMemo-guarded |
| Security | ✅ No concerns — pure UI, no eval/innerHTML |
| Accessibility | ✅ aria-hidden on backdrop, spellCheck={false} on inputs |
Nothing blocking here. The zero-width space documentation and the single-line scroll-sync on onChange are the two items most worth addressing before merge.
…#3653) Per PR review nit — the backdrop's trailing zero-width space was a literal invisible char in source (a readability/foot-gun, like a stray NUL). Use an explicit escape + comment instead. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VBLhGGNh35oMwTL53va1Y5
|
Thanks for the review. Triage: Addressed (
Verified, no change needed
Non-blocking overall — thanks for the thorough pass. |
|
Claude finished @Yeraze's task —— View job PR Review: feat(automations): highlight {{ }} tokens + flag typos in builder text fields
This is the second review pass, after
|
| Area | Status |
|---|---|
Core logic (tokenHints.ts) |
✅ Correct; minor double-trim nit |
UI component (TokenTextField.tsx) |
✅ Good; single-line scroll-sync is a known minor limitation |
Tests (tokenHints.test.ts) |
✅ Main paths covered; a few edge cases missing (non-blocking) |
| Catalog integration | ✅ tokens: true applied to all correct fields |
| CSS | ✅ Solid technique; color-mix() is modern-browser-only (acceptable) |
| Accessibility | ✅ aria-hidden on backdrop; focus ring on backdrop is cosmetic-only |
| TypeScript | ✅ tsc clean; type widening is safe |
| Security | ✅ No concerns — pure UI, no eval/innerHTML |
Nothing blocking. The implementation is solid. The remaining items (single-line scroll sync on onChange, missing edge-case tests) are all non-blocking nits.
Second of the two documented post-#3721 follow-ups (
AUTOMATION_ENGINE_PLAN.md§11).Why
{{ }}substitution tokens were indistinguishable from plain text in the builder, and a typo (e.g.{{ trigger.lastestVersion }}) silently rendered blank with no warning — exactly the confusion that surfaced while testing the Startup automation.Change
Token-bearing
text/textareafields (flaggedtokens: truein the catalog: message text + DM-to, notify title + body, condition values, setVar value) now render withTokenTextField— a highlight backdrop layered under a transparent input:{{ trigger.* }}/{{ var.* }}/{{ NOW }}tokens are blue when recognized, red + wavy underline when not.Recognition uses
tokenHints.ts(validTokenSet) built from the exportedTRIGGER_TOKENS+UNIVERSAL_TOKENSfor the current trigger plus the known variable names. It's a non-blocking hint (not a hard save gate) so a token the static registry doesn't enumerate can't block a legitimate save.Tests
tokenHints.test.tscoversvalidTokenSet(trigger tokens + universals + vars +NOW),unknownTokens(typo + unknown-var detection, empty-token + dedup handling), andtokenize(segment/known flags). Full suite 7518 passed, 0 failures; tsc + build clean.🤖 Generated with Claude Code