Jump to content

Myr

Clients
  • Posts

    758
  • Joined

  • Last visited

Reputation Activity

  1. Like
    Myr 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
    Myr reacted to Esther E. for an entry, IC5: Developer Center   
    As part of our commitment to encourage 3rd party development and extension, we have given our Developer Center a much needed makeover. A picture is worth a thousand words, but how about a video?
     
    Highlights
    The Developer Center now has its own dedicated tab in the ACP. What were previously tabs are now displayed on individual screens, making for a far less cluttered UI. You can easily switch from one application to another using the main menu or the button at the top right of the screen. We've implemented UI for some JSON files that previously had to be manually created; specifically acpsearch.json and furl.json We've replaced the "Support" button at the top of the ACP with a more helpful "Quick Links" dropdown menu. While this is not specific to developers, with easy access to things like the Task Manager and clearing caches, it's very handy for troubleshooting!  
    Application Landing Page
    When you open the Developer Center for a particular application, the landing page is designed to help you quickly access common functions, and to help you find any potential issues within your code.

     
    The Application Scanner currently checks for:
    Missing Admin CP Language Strings Missing Front-End Language Strings Missing EditorLocations extensions Missing FileStorage extensions Missing FrontNavigation extensions Missing FURLs Missing Email Templates  
    Language strings are grouped so that can you easily see where the missing strings were detected.

     
    We will continue to expand the scanners over the course of the next few months.
     
    Thoughts?
    What do you think? Are there any other useful features you'd like to see added to the Dev Center? What kind of scans can we implement on the landing page?
  3. Like
    Myr reacted to Esther E. for an entry, IC5: Extensions   
    We've been dropping hints about various development features that haven't yet made their appearance in our previous blog entries. Now that hooks are no longer a possibility, we've expanded our Extensions system to allow developers to integrate with other areas within the framework.
    This blog entry will give an overview of our new Extensions. We are working on updating our developer documentation to include these changes.
     
    AccountSettings
    Allows you to add tabs to the Account Settings page. This extension contains two methods:
    getTab
    Returns the key for the tab (or null to hide) getContent
    The tab content  
    Loader
    This extension was created primarily to allow you to load Javascript and CSS files in areas outside of your application, but has since been expanded to include other functionality. It is essentially an extension on the Dispatcher.
    Available methods:
    css
    Returns an array of CSS files to load js
    Returns an array of JS files to load checkForRedirect
    Redirect users to another location. This is especially useful for custom applications that would have previously bypassed an existing controller. customError
    Show a custom error message to the user instead of the standard IPS error messages.  
    SearchContent
    This is used to allow your application's content to the Search Index. Previously, the framework relied on the ContentRouter extension for this, and the use of the \IPS\Content\Searchable interface. The interface has been removed, and searchable classes are determined by the new extension.
    The SearchContent extension contains one required method, supportedClasses. You can also use this extension to override our default search logic for your content.
     
    Other New Extensions
    LoginHandler
    Allows you to create additional Login methods UIComment/UIItem/UINode/UIReview
    UI Extensions, described here, here, and here UserMenu
    Allows you to add content to various menus. Additional information can be found here.  
    New Commerce Extensions
    The following new extensions have been added to Commerce:
    Gateway
    Allows you to create new payment gateways LicenseKey
    Allows you to add new methods for generating and managing license keys Payout
    Allows you to create gateways for payouts  
    Deprecated Extensions
    The following Extensions are no longer supported and have been removed:
    BBCode ContentModeratorPermissions (use ModeratorPermissions instead) CreateMenu (replaced by UserMenu) IncomingEmail MemberForm  
    Reminder: Send us your Feedback
    Send us your questions or use-cases by submitting a topic here. Please note that this is a private forum; you will not see topics posted by others, so you are free to share code samples if necessary. We will review your questions, and then aggregate them into an FAQ. The deadline for your question to be considered for the FAQ is October 15. After that you may still submit questions in the Contributor forum, where we will do our best to respond.
     
  4. Like
    Myr reacted to Matt for an entry, Introducing Invision Community 5's development tools   
    When planning Invision Community 5, we knew we had a unique opportunity to hit the reset button.
    It's hard to believe, but how we work with the framework has been the same since 2013. The priorities we held a decade ago no longer align with our current vision.
    The landscape of modern frameworks has evolved, and we have adapted accordingly.
    When we initially designed the Invision Community 4 framework all those years ago, our goal was to create an open development platform. We aimed to empower you with the ability to extend virtually every function we built, granting complete freedom to shape our UI, workflows, and functionality according to your needs.
    However, over the decade, we have realised that this freedom has inadvertently become a prison. While monkey patching allowed the overloading of any method we had written, it came at a significant cost. Even the slightest change to our original method signatures could break an entire community, forcing you to update your applications.
    Ironically, the more we strived to enhance our framework, the less stable your applications became.
    We dismissed requests for proper workflows like extensions, webhooks, and event listeners, urging you to rely solely on method overloading, often having to copy chunks of code just to add a few lines of your own.
    Invision Community 5 represents a much-needed reset. It is a moment to reassess everything we know about extending frameworks and construct definitive pathways and workflows that serve you better.
    Our aim is for you to continue crafting exceptional applications that bring fresh functionality to the Invision Community while protecting the integrity of our core functionality.
    Change can be intimidating, but let us embrace this opportunity to bid farewell to outdated and fragile tools and pave the way for a collaborative future with precision-designed resources instead.
    In the coming weeks, we will delve deeply into the new development tools offered by Invision Community 5, but today, I wanted to give you a brief overview of what's to come for code development. We will do a near-future entry on creating themes with Invision Community 5.
    Out with the old
    Monkey patching via code hooks was the primary way to add functionality to Invision Community. However, it meant that we could not update our code base without risking breaking many popular applications, a situation that will only get worse as PHP starts to lock down type hinting and casting.
    Furthermore, IDEs have a tough time working out relationships between classes requiring special tools to create alias files to allow full use of many advanced tools of PHPStorm and other editors. Finally, monkey patching relied on heavy use of eval() which is not a very efficient PHP method.
    Monkey patching has been removed in Invision Community 5.
    Your IDE with Invision Community 4.

    Your IDE with Invision Community 5.

     
    Template hooks, as you know them, have also been removed. I only mention this now as they often go hand-in-hand with code hooks to add items to menus, data-attributes to blocks and CSS classes to many areas. We will do a more thorough blog on theme editing soon, but we still retain a way to hook into key areas.
    In with the new
    We will write a series of developer blogs to look in more detail at the new systems, but here is a quick overview of the new tools and a brief description of what they are capable of.
    Content Menus
    We have removed much of the menu logic for content items and comments from templates and created a simple, extensible way to add links to commonly used menus, such as the item moderation menu and the per-post 'three dots' menu. You no longer need a template hook to perform such a basic task.

    UIExtension
    This framework provides you with an easy way to add CSS, data-attributes and even templated HTML into specific areas within nodes and content items/comments. A common reason to create template hooks was to tweak the CSS classes or add data-attributes for client-side scripting.

    In the same way that we've stripped menus out of templates, we've removed the content item badges (pinned, hidden, etc.) and into the UIExtension making it easy to add your own badges to this area without the need for template or code hooks.
    Finally, UIExtension can add form fields into Invision Community content forms.
    Event Listeners
    The easiest way to describe this is like MemberSync but for content (items and comments), members, Commerce invoices and Commerce packages.
    Do you need to run your code each time a forum post is made? Not a problem. Do you need to run your code when a topic is locked? Perhaps when an item is viewed? All this and more is possible via the new listeners.
    The advantage is that you don't need to copy chunks of our code when overloading a single method in a hook. You write your clean code in an object-specific listener.

    What else?
    We have also undertaken a long overdue code clean-up. Every single file has been updated to update return types and function signature types and to use aliases instead of fully qualified names (for example, new Url() instead of new \IPS\Http\Url()).
    Many methods have been removed from the Content classes and moved into traits. Likewise, many interfaces are now traits to reuse code properly, reducing the behemoth-sized classes.
    Elsewhere, all the search indexing logic that was entwined in content and node classes has now been moved to the extension system, further reducing the noise and volume of key classes.
    A Quick Recap
    Generic broad reaching tools such as monkey patching and template overloading have been removed. New precision tools with a specific use-case have been created. There are less opportunities to overwrite and change our UI and functionality but easier ways to extend and create new functionality. The future
    We have worked hard on these development tools to ensure that most of what you do now can be achieved in Invision Community 5. We have had input from various stakeholders, including those who regularly create modifications for Invision Community to ensure our new tools are fit for purpose.
    Through the alpha and beta testing phase, we want your feedback, and we will listen to your suggestions. We cannot promise that you can do everything with Invision Community 5 that you currently do, which is intentional, but we are confident that you can still hit all the major beats. We want to protect our UI and functionality a little more but encourage you to build amazing new functionality to work alongside Invision Community 5.
    Together, we will shape the next era of Invision Community.
×
×
  • Create New...