Skip to content

feat: render iMessage text decorations from {decoration:content} markup#14

Open
pdsullivan wants to merge 1 commit into
mainfrom
feat/imessage-text-decorations
Open

feat: render iMessage text decorations from {decoration:content} markup#14
pdsullivan wants to merge 1 commit into
mainfrom
feat/imessage-text-decorations

Conversation

@pdsullivan

Copy link
Copy Markdown
Contributor

What

The system prompt already instructs Claude to style and animate words using {bold:...}, {shake:...}, {explode:...}, etc. (iMessage text decorations), but nothing parsed that markup — so users saw literal braces in the message. This PR wires up the actual rendering path.

Changes

  • src/text/decorations.ts
    • parseDecorations() — converts {name:content} markup into plain text plus a text_decorations[] array (character ranges + style/animation). Handles overlap (first match wins), unknown names (left as-is), emoji, and adjacency.
    • processResponse(text, isIMessage) — for iMessage, parses decorations and cleans up whitespace quirks while keeping ranges aligned; for SMS/RCS, strips the markup entirely (those channels can't render decorations).
  • src/linq/client.tssendMessage() takes an optional textDecorations arg and attaches it to the text message part (text_decorations). Adds TextDecoration / style / animation types.
  • src/index.ts — routes each outgoing message through processResponse() based on channel, replacing the old inline cleanResponse().
  • src/text/decorations.test.ts — 32 tests (parsing, range math, per-channel behavior, edge cases).
  • package.json — adds test script (tsx --test).

Test plan

  • npm run build passes
  • npm test — 32/32 pass
  • Text the live iMessage number and confirm decorations render natively (and that SMS/RCS get clean plain text)

Note

Independent of #13 (the Sonnet 4.6 hotfix) — separate concern, separate branch off main.

The system prompt already teaches Claude to style/animate words with
{bold:...}, {shake:...}, etc., but nothing parsed that markup — it was
sent to users as literal braces. This wires up the rendering path.

- src/text/decorations.ts: parseDecorations() converts {name:content}
  markup into plain text + a text_decorations[] array (ranges + style/
  animation). processResponse() applies it for iMessage and strips the
  markup entirely for SMS/RCS (which can't render decorations).
- src/linq/client.ts: sendMessage() accepts optional textDecorations and
  attaches them to the text message part (text_decorations).
- src/index.ts: routes each outgoing message through processResponse()
  based on the channel, replacing the old inline cleanResponse().
- decorations.test.ts: 32 tests covering parsing, range math, channel
  behavior, and edge cases (overlap, unknown names, emoji, adjacency).
- package.json: add `test` script (tsx --test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant