Skip to content

Updated transistor renderer#26279

Open
9larsons wants to merge 4 commits intomainfrom
upd-transistor-renderer
Open

Updated transistor renderer#26279
9larsons wants to merge 4 commits intomainfrom
upd-transistor-renderer

Conversation

@9larsons
Copy link
Contributor

@9larsons 9larsons commented Feb 5, 2026

ref https://linear.app/ghost/issue/NY-1005/

  • added dynamic replacement of {uuid} using the same mechanism as content-gating at the API level
  • updated renderer
  • added tests

This PR fully wires up the substitution of {uuid} in the outputted content (API response). The token is set within the rendered html content so that we don't need to re-render the content at request time for each member. This instead allows us to do it at the API, just like we do with content visibility, which is also leveraged by this functionality.

This handles the actual display on the frontend. This is difficult to test because you need the integration set up with an available domain - you can see the build on site 352618 on staging.

This does not change the email rendering pipeline.

The Editor > Post Preview > Web view is still broken - we have to follow up with changes to inject a valid uuid in order to be able to preview it there. That is tracked separately.

no ref
- added dynamic replacement of {uuid} within the {{content}} block
- updated renderer
- added tests
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 5, 2026

Walkthrough

The changes implement a deferred UUID substitution mechanism for embedded content. The transistor-renderer is modified to use a fixed {uuid} placeholder in URLs instead of requiring memberUuid at render time. Separately, post-gating.js adds logic to replace URL-encoded {uuid} placeholders (%7Buuid%7D) with actual member.uuid values during post-processing. This shifts UUID injection from render time to a later processing stage. Test coverage is added for both the post-gating substitution logic and transistor-renderer behavior across web and email rendering paths.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Updated transistor renderer' directly relates to the main change in the PR, which updates the transistor renderer to use dynamic {uuid} replacement.
Description check ✅ Passed The PR description clearly relates to the changeset, describing the dynamic {uuid} replacement mechanism, renderer updates, and test additions referenced in all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch upd-transistor-renderer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@9larsons 9larsons requested a review from EvanHahn February 5, 2026 21:21
@9larsons 9larsons marked this pull request as ready for review February 5, 2026 21:21
@@ -0,0 +1,124 @@
const assert = require('assert/strict');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should've added these tests with the original renderer commit.

const iframe = document.createElement('iframe');
iframe.setAttribute('width', '100%');
iframe.setAttribute('height', '400');
iframe.setAttribute('height', '325');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches the content height based on the embed. You can see this here with https://partner.transistor.fm/ghost/embed/7d75f320-d0ed-4e6a-9ef5-840163033dbd for the moment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little concerned that we have a fixed height and scrolling=no below. But that's probably an issue for another ticket.


const embedUrl = new URL(`https://partner.transistor.fm/ghost/embed/${memberUuid}`);
// Use {uuid} placeholder - content.js will substitute with member UUID at request time
const embedUrl = new URL(`https://partner.transistor.fm/ghost/embed/{uuid}`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer get to null check here because it must get substituted at the API level.

const member = frame.original.context.member;
if (member && member.uuid && attrs.html) {
attrs.html = attrs.html.replace(/%7Buuid%7D/gi, member.uuid);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed best to handle this as encoded, though I'm ambivalent here.

Copy link
Contributor

@EvanHahn EvanHahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some non-blocking comments.

I think the ref in the PR description is wrong. (Should it be NY-998?)


gating.forPost(attrs, frame);

// Non-encoded {uuid} should NOT be replaced
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think this comment is unnecessary, based on the title of the test.

Suggested change
// Non-encoded {uuid} should NOT be replaced

const result = renderForWeb(getTestData());

assert.ok(result.html);
// URL constructor encodes {uuid} to %7Buuid%7D
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think this comment is unnecessary.

Suggested change
// URL constructor encodes {uuid} to %7Buuid%7D

it('renders iframe with URL-encoded %7Buuid%7D placeholder', function () {
const result = renderForWeb(getTestData());

assert.ok(result.html);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think all of these assert.ok(result.html)s are unnecessary because you immediately check something about them later. I'd probably remove unless you're getting type errors.

const result = renderForEmail(getTestData({accentColor: null}));

assert.ok(result.html);
// Default is #15171A
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think it's clear without this comment.

Suggested change
// Default is #15171A

const iframe = document.createElement('iframe');
iframe.setAttribute('width', '100%');
iframe.setAttribute('height', '400');
iframe.setAttribute('height', '325');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little concerned that we have a fixed height and scrolling=no below. But that's probably an issue for another ticket.

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.

2 participants