Skip to content

Conversation

@cmraible
Copy link
Collaborator

@cmraible cmraible commented Dec 9, 2025

ref https://linear.app/ghost/issue/NY-849/editor-should-be-restricted

The Koenig editor that we're using in the member welcome emails modal is currently unrestricted, which allows for any and all cards to be used. It doesn't have the plugins necessary to insert them, but if you paste content from a post into the editor, it will try to include the cards and make the editor largely unusable.

This fixes that by restricting the allowed nodes to only the BASIC_NODES defined in @tryghost/koenig-lexical, which only includes basic text formatting (bold, italics), lists, links, and the TK node.


Remaining Issues

This solves much of the problem, but there are some bits that this doesn't completely solve:

  • BASIC_NODES includes the TK card, which we arguably don't want here
  • BASIC_NODES doesn't include extended-text, so any sites that have already created welcome emails (luckily only local/internal ones) will throw an error when trying to load the content from the DB, since it has extended-text nodes in it.

Path Forward

I think ultimately we'll want to create our own list of valid nodes in keonig-lexical for this specific use-case. That allows us to tailor the editor to our exact needs, so we can e.g. remove the TK node, and eventually add Headings, Buttons, etc.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 9, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chris-ny-849-editor-should-be-restricted

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.


// Default welcome email content in Lexical JSON format
// Uses __GHOST_URL__ placeholder which Ghost replaces with the actual site URL
const DEFAULT_FREE_LEXICAL_CONTENT = '{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Welcome! Thanks for subscribing — it\'s great to have you here.","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"You\'ll now receive new posts straight to your inbox. You can also log in any time to read the ","type":"extended-text","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"full archive","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"link","version":1,"rel":"noreferrer","target":null,"title":null,"url":"__GHOST_URL__/"},{"detail":0,"format":0,"mode":"normal","style":"","text":" or catch up on new posts as they go live.","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"A little housekeeping: If this email landed in spam or promotions, try moving it to your primary inbox and adding this address to your contacts. Small signals like that help your inbox recognize that these messages matter to you.","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"Have questions or just want to say hi? Feel free to reply directly to this email or any newsletter in the future.","type":"extended-text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1},{"children":[],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}';
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The BASIC_NODES from @tryghost/koenig-lexical does not include the "extended-text" node, so when this default content loaded into the editor it threw an error.

Note: this kind of sucks, since some sites (luckily only local/internal ones) already have this default content in the DB, which means the editor will throw an error next time it's loaded.

@cmraible
Copy link
Collaborator Author

cmraible commented Dec 9, 2025

This doesn't feel like the right solution. I think we'll ultimately want to create a set of nodes specifically for this use-case, including links, lists, headings, extended-text, etc. and without the TK node. Closing this PR since it doesn't quite solve the problem completely.

@cmraible cmraible closed this Dec 9, 2025
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