Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added visibility rendering to Call to Action card #1436

Conversation

kevinansfield
Copy link
Member

@kevinansfield kevinansfield commented Feb 4, 2025

ref https://linear.app/ghost/issue/PLG-332

  • used visibility render method on CTA card's render output to wrap contents where necessary

ref https://linear.app/ghost/issue/PLG-332

- extracted visibility rendering logic and adapted to be more generalised for use in other cards
ref https://linear.app/ghost/issue/PLG-332

- used visibility render method on CTA card's render output to wrap contents where necessary
Copy link

coderabbitai bot commented Feb 4, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/kg-default-nodes/lib/nodes/call-to-action/calltoaction-renderer.js

Oops! Something went wrong! :(

ESLint: 8.57.0

Error: Failed to load parser '@babel/eslint-parser' declared in 'packages/kg-default-nodes/.eslintrc.js': Cannot find module '@babel/eslint-parser'
Require stack:

  • /packages/kg-default-nodes/.eslintrc.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Function.resolve (node:internal/modules/helpers:145:19)
    at Object.resolve (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2346:46)
    at ConfigArrayFactory._loadParser (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3325:39)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3099:43)
    at _normalizeObjectConfigDataBody.next ()
    at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3040:20)
    at _normalizeObjectConfigData.next ()
    at ConfigArrayFactory.loadInDirectory (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2886:28)
    at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)
packages/kg-default-nodes/lib/nodes/html/html-renderer.js

Oops! Something went wrong! :(

ESLint: 8.57.0

Error: Failed to load parser '@babel/eslint-parser' declared in 'packages/kg-default-nodes/.eslintrc.js': Cannot find module '@babel/eslint-parser'
Require stack:

  • /packages/kg-default-nodes/.eslintrc.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Function.resolve (node:internal/modules/helpers:145:19)
    at Object.resolve (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2346:46)
    at ConfigArrayFactory._loadParser (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3325:39)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3099:43)
    at _normalizeObjectConfigDataBody.next ()
    at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3040:20)
    at _normalizeObjectConfigData.next ()
    at ConfigArrayFactory.loadInDirectory (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2886:28)
    at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)
packages/kg-default-nodes/lib/utils/visibility.js

Oops! Something went wrong! :(

ESLint: 8.57.0

Error: Failed to load parser '@babel/eslint-parser' declared in 'packages/kg-default-nodes/.eslintrc.js': Cannot find module '@babel/eslint-parser'
Require stack:

  • /packages/kg-default-nodes/.eslintrc.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1248:15)
    at Function.resolve (node:internal/modules/helpers:145:19)
    at Object.resolve (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2346:46)
    at ConfigArrayFactory._loadParser (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3325:39)
    at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3099:43)
    at _normalizeObjectConfigDataBody.next ()
    at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3040:20)
    at _normalizeObjectConfigData.next ()
    at ConfigArrayFactory.loadInDirectory (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2886:28)
    at CascadingConfigArrayFactory._loadConfigInAncestors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3871:46)

Walkthrough

This update refactors rendering logic for call-to-action and HTML nodes by centralizing visibility handling through a newly introduced renderWithVisibility function. The changes modify both node renderers to delegate visibility and formatting responsibilities to the new function, introduce helper functions in the visibility module, and add comprehensive tests for various visibility scenarios across email and web outputs.

Changes

File(s) Change Summary
packages/kg-default-nodes/lib/nodes/call-to-action/calltoaction-renderer.js
packages/kg-default-nodes/lib/nodes/html/html-renderer.js
Updated node renderers to remove direct visibility handling logic and instead call renderWithVisibility. HTML formatting adjustments applied in anchor tags.
packages/kg-default-nodes/lib/utils/visibility.js Added new exported function renderWithVisibility along with helper functions (_getRenderContent, _renderWithEmailVisibility, _renderWithWebVisibility) and an import for renderEmptyContainer to support conditional rendering based on visibility.
packages/kg-default-nodes/test/nodes/call-to-action.test.js
packages/kg-default-nodes/test/utils/visibility.test.js
Reorganized imports and introduced new test cases to verify the rendering behavior under both email and web visibility conditions, including handling of legacy visibility formats.

Sequence Diagram(s)

sequenceDiagram
    participant CTA as CallToActionNode
    participant RCTA as renderCallToActionNode
    participant RWV as renderWithVisibility
    participant Util as Visibility Helpers

    CTA->>RCTA: Invoke renderCallToActionNode(node, options)
    RCTA->>RWV: Pass output and visibility settings
    RWV->>Util: Evaluate visibility (email or web)
    Util-->>RWV: Return modified content based on visibility
    RWV-->>RCTA: Return rendered output
    RCTA-->>CTA: Send final rendering
Loading
sequenceDiagram
    participant HTML as HtmlNode
    participant RHTML as renderHtmlNode
    participant RWV as renderWithVisibility
    participant Util as Visibility Helpers

    HTML->>RHTML: Invoke renderHtmlNode(node, options)
    RHTML->>RWV: Delegate visibility handling if required
    RWV->>Util: Process based on email/web conditions
    Util-->>RWV: Return updated render output
    RWV-->>RHTML: Return final content
    RHTML-->>HTML: Deliver rendered HTML
Loading

Possibly related PRs

Suggested reviewers

  • ronaldlangeveld

Poem

I'm a little rabbit, hopping through the code,
Skipping over branches on this brand new road.
Visibility now shines, in email and web alike,
With cleaner paths and helpers that spike.
A merry hop to progress, with each refined byte! 🐰✨

Tip

🌐 Web search-backed reviews and chat
  • We have enabled web search-based reviews and chat for all users. This feature allows CodeRabbit to access the latest documentation and information on the web.
  • You can disable this feature by setting web_search: false in the knowledge_base settings.
  • Please share any feedback in the Discord discussion.
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@kevinansfield kevinansfield changed the title add visibility rendering to cta card Added visibility rendering to Call to Action card Feb 4, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
packages/kg-default-nodes/lib/utils/visibility.js (2)

81-92: Add error handling for invalid render types.

The _getRenderContent function should handle invalid type values to prevent potential runtime errors.

 function _getRenderContent({element, type}) {
+    if (!element) {
+        return '';
+    }
     if (type === 'inner') {
         return element.innerHTML;
     } else if (type === 'value') {
         if ('value' in element) {
             return element.value;
         }
         return '';
     } else {
+        // Default to outerHTML for unknown types
         return element.outerHTML;
     }
 }

40-77: Consider adding JSDoc comments for better documentation.

The renderWithVisibility function is a key utility that would benefit from detailed documentation of its parameters and return value.

+/**
+ * Renders content with visibility rules for web and email targets.
+ * @param {Object} originalRenderOutput - The original render output containing element and type.
+ * @param {Object} visibility - The visibility rules for web and email.
+ * @param {Object} options - Rendering options including target.
+ * @returns {Object} The rendered output with visibility rules applied.
+ */
 export function renderWithVisibility(originalRenderOutput, visibility, options) {
packages/kg-default-nodes/lib/nodes/call-to-action/calltoaction-renderer.js (1)

84-84: Add null checks before accessing firstElementChild.

The code assumes emailDiv and element will always have a firstElementChild. Add null checks to handle edge cases gracefully.

-        return renderWithVisibility({element: emailDiv.firstElementChild}, node.visibility, options);
+        const firstChild = emailDiv.firstElementChild;
+        if (!firstChild) {
+            throw new Error('Failed to render CTA email template');
+        }
+        return renderWithVisibility({element: firstChild}, node.visibility, options);

-    return renderWithVisibility({element: element.firstElementChild}, node.visibility, options);
+    const firstChild = element.firstElementChild;
+    if (!firstChild) {
+        throw new Error('Failed to render CTA template');
+    }
+    return renderWithVisibility({element: firstChild}, node.visibility, options);

Also applies to: 91-91

packages/kg-default-nodes/test/nodes/call-to-action.test.js (1)

259-283: Tests look good, but could be more descriptive and DRY.

The test cases effectively verify visibility rendering for both web and email targets. However, consider these improvements:

  1. More descriptive test names:
-it('should render with web visibility'
+it('should wrap content in gated block comments when rendering for web with visibility settings'

-it('should render with email visibility'
+it('should add segment data attributes when rendering for email with visibility settings'
  1. Extract common visibility setup:
+beforeEach(function () {
+    // ... existing setup ...
+    
+    // Common visibility setup
+    dataset.visibility = {...utils.visibility.buildDefaultVisibility()};
+});

 it('should render with web visibility', editorTest(function () {
     exportOptions.target = 'web';
-    dataset.visibility = {...utils.visibility.buildDefaultVisibility(), web: {nonMember: false, memberSegment: 'status:free,status:-free'}};
+    dataset.visibility.web = {nonMember: false, memberSegment: 'status:free,status:-free'};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 222a942 and 4b2f2e7.

📒 Files selected for processing (5)
  • packages/kg-default-nodes/lib/nodes/call-to-action/calltoaction-renderer.js (3 hunks)
  • packages/kg-default-nodes/lib/nodes/html/html-renderer.js (2 hunks)
  • packages/kg-default-nodes/lib/utils/visibility.js (2 hunks)
  • packages/kg-default-nodes/test/nodes/call-to-action.test.js (2 hunks)
  • packages/kg-default-nodes/test/utils/visibility.test.js (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Node 20.11.1
🔇 Additional comments (3)
packages/kg-default-nodes/lib/nodes/html/html-renderer.js (1)

3-3: LGTM! Clean refactoring of visibility handling.

The changes effectively delegate visibility handling to the renderWithVisibility utility function, making the code more maintainable and consistent with other renderers.

Also applies to: 20-22

packages/kg-default-nodes/test/utils/visibility.test.js (1)

62-200: LGTM! Excellent test coverage.

The test suite is comprehensive and well-structured, covering:

  • Email and web targets
  • Different render types
  • Old and new visibility formats
  • Edge cases and error conditions
packages/kg-default-nodes/test/nodes/call-to-action.test.js (1)

3-4: LGTM!

Clean organization of imports improves readability.

@kevinansfield kevinansfield merged commit c6e63a3 into TryGhost:main Feb 5, 2025
2 checks passed
@kevinansfield kevinansfield deleted the add-visibility-rendering-to-cta-card branch February 5, 2025 08:04
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