back to home

fastmail / Squire

The rich text editor for arbitrary HTML.

4,897 stars
414 forks
56 issues
TypeScriptHTMLJavaScript

AI Architecture Analysis

This repository is indexed by RepoMind. By analyzing fastmail/Squire in our AI interface, you can instantly generate complete architecture diagrams, visualize control flows, and perform automated security audits across the entire codebase.

Our Agentic Context Augmented Generation (Agentic CAG) engine loads full source files into context on-demand, avoiding the fragmentation of traditional RAG systems. Ask questions about the architecture, dependencies, or specific features to see it in action.

Source files are only loaded when you start an analysis to optimize performance.

Embed this Badge

Showcase RepoMind's analysis directly in your repository's README.

[![Analyzed by RepoMind](https://img.shields.io/badge/Analyzed%20by-RepoMind-4F46E5?style=for-the-badge)](https://repomind.in/repo/fastmail/Squire)
Preview:Analyzed by RepoMind

Repository Overview (README excerpt)

Crawler view

Squire Squire is an HTML5 rich text editor, which provides powerful cross-browser normalisation in a flexible lightweight package (only 16KB of JS after minification and gzip, with no dependencies!). It was designed to handle email composition for the Fastmail web app. The most important consequence of this (and where Squire differs from most other modern rich text editors) is that it must handle arbitrary HTML, because it may be used to forward or quote emails from third-parties and must be able to preserve their HTML without breaking the formatting. This means that it can't use a more structured (but limited) internal data model (as most other modern HTML editors do) and the HTML remains the source-of-truth. The other consequence is excellent handling of multiple levels of blockquotes. Squire is designed to be integrated with your own UI framework, and so does not provide its own UI toolbar, widgets or overlays. Instead, you get a component you can insert in place of a and manipulate programmatically, allowing you to integrate seamlessly with the rest of your application and lose the bloat of having two UI toolkits loaded. Squire supports all reasonably recent browsers. It no longer supports any version of IE. In addition to its use at Fastmail, it is also currently used in production at ProtonMail, SnappyMail, StartMail, Tutanota, Zoho Mail, Superhuman and Teamwork Desk, as well as other non-mail apps including Google Earth (drop me a line if you're using Squire elsewhere, I'm always interested to hear about it!). For a demo of the latest version with a production-level UI integration, sign up for a free Fastmail trial :). There's also a very bare-bones integration in the repo; just clone it and open . If you are reporting a bug, please report the steps to reproduce using , to make sure it's not a bug in your integration. Installation and usage • Add Squire to your project: • In your code, • Create your editor by calling . Invoke with script tag Squire can also be used in a script tag: • Add a tag to load in (or for the debuggable unminified version): • Get a reference to the DOM node in the document that you want to make into the rich textarea, e.g. . • Call . This will instantiate a new Squire instance. Please note, this will remove any current children of the node; you must use the command after initialising to set any content. Editor lifecycle You can have multiple Squire instances in a single page without issue. If you are using the editor as part of a long lived single-page app, be sure to call once you have finished using an instance to ensure it doesn't leak resources. Security Malicious HTML can be a source of XSS and other security issues. You MUST provide a method to safely convert raw HTML into DOM nodes to use Squire. Squire will automatically integrate with DOMPurify to do this if present in the page. Otherwise you must set a custom function in your config. • **sanitizeToDOMFragment**: A custom sanitization function. This will be called instead of the default call to DOMPurify to sanitize the potentially dangerous HTML. It is passed two arguments: the first is the string of HTML, the second is the Squire instance. It must return a DOM Fragment node belonging to the same document as the editor's root node, with the contents being clean DOM nodes to set/insert. Advanced usage Squire provides an engine that handles the heavy work for you, making it easy to add extra features. With the method you can easily add or remove any inline formatting you wish. And the method can be used to make complicated block-level changes in a relatively easy manner. If you need more commands than in the simple API, I suggest you check out the source code (it's not very long), and see how a lot of the other API methods are implemented in terms of these two methods. The general philosophy of Squire is to allow the browser to do as much as it can (which unfortunately is not very much), but take control anywhere it deviates from what is required, or there are significant cross-browser differences. As such, the method is not used at all; instead all formatting is done via custom functions, and certain keys, such as 'enter' and 'backspace' are handled by the editor. Setting the default block style By default, the editor will use a for blank lines, as most users have been conditioned by Microsoft Word to expect Enter to act like pressing return on a typewriter. If you would like to use tags (or anything else) for the default block type instead, you can pass a config object as the second parameter to the Squire constructor. You can also pass a set of attributes to apply to each default block: var editor = new Squire(document, { blockTag: 'P', blockAttributes: { style: 'font-size: 16px;' } }); Determining button state If you are adding a UI to Squire, you'll probably want to show a button in different states depending on whether a particular style is active in the current selection or not. For example, a "Bold" button would be in a depressed state if the text under the cursor is already bold. The efficient way to determine the state for most buttons is to monitor the "pathChange" event in the editor, and determine the state from the new path. If the selection goes across nodes, you will need to call the method for each of your buttons to determine whether the styles are active. See the and documentation for more information. License Squire is released under the MIT license. See LICENSE for full license. API addEventListener Attach an event listener to the editor. The handler can be either a function or an object with a method. This function or method will be called whenever the event fires, with an event object as the sole argument. The following events may be observed: • **focus**: The editor gained focus. • **blur**: The editor lost focus • **keydown**: Standard DOM keydown event. • **keypress**: Standard DOM keypress event. • **keyup**: Standard DOM keyup event. • **i…