Jump to content

abobader

Clients
  • Posts

    705
  • Joined

Reputation Activity

  1. Like
    abobader reacted to Matt Finger for an entry, IC5: The New Editor   
    In 2024, a secure WYSIWYG Editor has become a complex intricate thing.
    Copy/paste bundle files have largely been phased out in favor of complicated NPM repos and build tools. What was more or less just "HTML Manipulation" has evolved to abstract content models with dynamic rules on how to actually render the content to HTML. Then, for kicks, throw in the requirement that this editor needs to work in non-standard cases like the drag and drop page builder and live topics. The solution for Invision Community 5 is a new, custom, state of the art Editor built using ReactJS and Tiptap.
    In this article, I'll cover high level advantages, technical highlights and what's possible with 3rd party extensions. 
    If you want to know more about the editor functionality, then see my other blog here.
    This story begins after we switched to CKEditor5 over a year ago. It is a decent product, but it had several serious limitations in a distributed platform like Community. We compared just about every editor currently on the market, and even considered building an editor completely from scratch, and ultimately landed on creating a custom editor using ReactJS and Tiptap.
     
    A lightweight package
    The v5 editor bundle size is small, coming to about 2mb in total (and it's split into separate chunks loaded ad-hoc, each one cached in the browser, so in practice much less data actually "loads"). After optimizing and tweaking CKEditor5, the smallest we could get it was over 50mb; now some build tool experts could probably wrangle that cke package to a smaller size, but I doubt it'd come anywhere close to Tiptap with all the features we added.
    It's also worth noting that, during operation, Tiptap had by far the lowest impact on browser memory consumption, and stubborn memory leaks never came up with this architecture. Part of this comes from taking advantage of ReactJS's stateful nature, but I think the most significant thing is that Tiptap doesn't have loose logic hanging around.
     
    How a modern WYSIWYG works (the short version)
    As I previously alluded to, editors today don't directly manipulate HTML at all. Instead, they store a Content Model according to a Schema.
    Different platforms may use different terms, but the content schema consists of the following Entities
    Nodes - Actual containers to put content in. Think blockquotes, headings or lists. Nodes are then stored in the document in a tree Text and Inline Nodes - Text is, well, text. It is exclusively just a string of characters; one way to think of it is, if it can go in a text message, it's text. Inline nodes, on the other hand, are not true "characters" but displayed inline with characters. Think custom emoticons and mentions. Marks - Styles and/or data that is applied over a range of text. Marks are similar to Nodes except that marks can overlap. For example, it if text is italic and bold, it makes no difference if it's bold inside italic or vise versa. Moreover, it it most accurate to simply say that text is just both italic and bold; this data is stored in Marks. In old editors, like CKEditor4, this was often just thrown into a "style" attribute which led to all sorts of issues and overhead processing. (These are not what CKEditor calls "marks" FYI, they call this concept "text attributes", in case anyone has existing CKE knowledge) All the above entities rely on Converters to generate them from HTML and then reconvert back into HTML. When the editor starts, it uses those converts to convert the initial data into the Content Model. Then, any change is made to the Content Model directly, which is continuously being converted back into HTML for the user to see.
    Security and Consistency
    The Schema and architecture add a layer of complexity but provide much better security, consistency and reliability because it only allows whitelisted content structures. For example, if I inserted something with the attribute style="color:white; transform: rotate(45deg)", the transform and color will be stripped out unless there's an existing converter to convert it to a Mark.
    Another example good example is simple bold styling: I can define several converters to parse the bold Mark: one for <b> tags, one for <strong> and one for style="font-weight: bold", and have them all convert back into a <strong> tag.
    Lastly, this gives us the assurance that, for any style, there is a user interface to manipulate and manage it. For this reason, source editing was removed because you won't ever need to fall back to source editing.
    I could go on for hours (seriously, don't get me started) but that's more than enough context to understand the rest of this article.
     
    Extending the Editor in Invision
    Another limitation of CKEditor5 in a distributed platform, where individual admins may want to customize, is that all Plugins have to be present at build not at runtime. This would pretty much mean no extending the editor, just rearranging the toolbar and flipping certain builtin features on and off.
    Fortunately, in Tiptap we were able to extend their internal node, mark and extension APIs. We'll have a more complete dev guide, but essentially all nodes, marks and extensions, which I'll just call "extensions" collectively, are rolled into the existing app system. There are 2 reasons we did this instead of just "buttons" like Invision 4, where you can just upload the CKEditor4 plugin zip file:
    It relies on using PHP to parse JavaScript to get things like the button title and stuff. If you create a valid plugin but define things in a slightly different way than expected, such as adding the name to the wrong line in the file, the plugin upload fails. Plugins/extensions are not buttons. Many CKE plugins have multiple buttons and many have none. This make management difficult because sometimes there isn't a button to remove and you have to reset all plugins, or you want to remove just one and 5 others disappear with it. Also, mostly all plugins add a new type of content; this type of content needs to be whitelisted Now, you may be thinking, "like the editor itself, won't the server side HTML Parser will strip any content that is not whitelisted"? Well, the answer is yes and we added a new AdminCP Dev Center tool to create Parser Whitelist Rules inside Invision Community Apps (again more on all this later). With the coupling of the Parser Whitelist and Editor Extensions, admins can rest assured that their editors will just "work" when you install Extensions.
    If you want to prematurely prepare to create Invision Community 5 Editor Extensions, have a look at Tiptap's Dev API Documentation, specifically the methods Node.create(), Mark.create() and Extension.create(). We've added wrappers for those three methods, in addition to an interface to add and position buttons in the toolbar.

    Please let me know if you have any questions!
  2. Like
    abobader reacted to Matt Finger for an entry, Development update for August 2022   
    Welcome to our August (and June and July) developer's Update!
    We've had a busy summer so far, with our team working on the final touches to 4.7 which introduced range of new Cloud specific features. In our August release we also added a way to schedule topics.
    @Jordan Miller announced the new solutions improvements here, this will be included in our September release (4.7.2)
    PHP8 Compatibility Scanner
    We are excited to announce that as a platform we (finally) are starting the process of migrating from PHP7 to PHP8 in order to keep the software secure, modern, and performant.
    Since PHP8 includes some breaking changes from PHP7, we've built a Method Scanner that will iterate through third party apps and plugins to find fatal issues, disabling any such customizations on upgrade. The apps and plugins disabled in this manner will not be able to be re-enabled until they are updated with the fixes. Developers, please make sure that your resources are fully tested with PHP 8+ and the method signatures match.
    For developers, the main issue the scanner looks for is instances in which a method's signature is altered when extending a class; this can cause fatal errors that make even the AdminCP inaccessible. Violating code can be found both in your hooks as well as other PHP classes your app/plugin uses. See the PHP8 Incompatible Apps and Plugins in the AdminCP Support Page to see exactly the issues identified and how to resolve:

     
    Pre-Upgrade Resource Checker
    We're also introducing a new AdminCP upgrade step to check installed resources for whether compatibility updates are available for version they're upgrading to.

     
    Here is the full changelog for our upcoming September release.
    Core - Added ACP Tool to scan all hooks to identify PHP8 fatal errors related to method overloading. - Added AdminCP new search terms to guide admins to the new areas. - Added a pre-upgrade Marketplace compatibility check. - Fixed an issue where a large number of profile field options can break the page layout on the member stats overview page. - Fixed an issue where members following an item may not be following the remaining item after a merge. - Fixed an issue where word filters could cause an item to be held for approval even if the author had more than the required number of posts to bypass. - Fixed an issue with hCaptcha where an incorrect language override could be requested. - Fixed an issue where it was possible to create an alert with forced reply from a moderator/admin account with a disabled messenger. - Fixed an issue where editing the ACP => System => Postings page with disabled registrations would throw an exception while the submission. - Fixed an issue where some alerts were not shown if they had an end date. - Fixed an issue where post to Twitter could potentially result in an uncaught exception - Fixed an issue where the oauth configuration page was missing the required css files. - Fixed an issue where a report title may appear in trending content (does not expose any sensitive data). - Fixed an issue where removing a manually added badge would not remove the badge - Fixed an issue where the rank progression chart may not work when non-default ranks are used. - Fixed an issue where the achievements rebuild may fail. - Fixed an issue where content tags from content created by the RSS Import feature could be associated with a guest account. - Fixed an issue where alerts could not be dismissed if they had long titles. - Fixed an issue where search options may break on profiles when status updates were disabled. Pages - Fixed an issue where orphaned categories could break syncing from topics. - Fixed an issue when using the REST API to fetch records where fields may not have the image lazyload removed. Forums - Added multiple improvements to "Mark as solution" including a re-engagement email, new UI to prompt authors to mark a reply as the solution and new stats. - Fixed an issue where the default forum views may not be used for guests. - Fixed an issue where soft deleted items may be archived and then subsequently deleted leaving orphaned reports. - Fixed an issue where a malformed findComment link caused a 404 error instead of loading the topic from the start. Commerce - Fixed a typo on the invoice settings page. - Fixed an issue on the credits page - Fixed an issue where deleting a subscription package would leave some orphaned data in the database. Changes affecting third-party developers and designers - Fixed an issue where plugin index.html files may get included as CSS causing a browser rendering issue.  
×
×
  • Create New...