Browse by type
Squire is an HTML5 rich text editor, which provides powerful cross-browser normalisation in a flexible lightweight package (only 16.5KB 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 was 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 <textarea> and manipulate programatically, 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, and even moderately old, browsers (even IE11, although this is not tested much these days).
In addition to its use at FastMail, is is also currently used in production at ProtonMail, Zoho Mail and Superhuman, as well as other non-mail apps (drop me a line if you're using Squire elsewhere, I'm always interested to hear about it!).
An example UI integration can be tried at http://neilj.github.io/Squire/. Please note though, this is an out-of-date version of Squire and a slightly buggy implementation written by an intern many years ago. 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 Demo.html. If you are reporting a bug, please report the steps to reproduce using Demo.html, to make sure it's not a bug in your integration.
build/ directory onto your server.<style> block in document.html to add the default styles you
would like the editor to use (or link to an external stylesheet).<textarea>, use an
<iframe src="https://github.com/fastmail/Squire/raw/v1.9.0/path/to/document.html">.load event of the iframe. When
this fires you can grab a reference to the editor object through
iframe.contentWindow.editor.editor object to set and get data and integrate
with your application or framework.Squire can also be used without an iframe for the document. To use it this way:
<script> tag to load in build/squire.js (or squire-raw.js for the debuggable unminified version).node = document.getElementById( 'editor-div' ).editor = new Squire( node ). This will instantiate a new Squire instance. Please note, this will remove any current children of the node; you must use the setHTML command after initialising to set any content.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 editor.destroy() once you have finished using an instance to ensure it doesn't leak resources.
Malicious HTML can be a source of XSS and other security issues. I highly recommended you use DOMPurify with Squire to prevent these security issues. If DOMPurify is included in the page (with the standard global variable), Squire will automatically sanitise any HTML passed in via setHTML or insertHTML (which includes HTML the user pastes from the clipboard).
You can override this by setting properties on the config object (the second argument passed to the constructor, see below). The properties are:
Boolean
Should the HTML passed via calls to setHTML be passed to the sanitizer? If your app always sanitizes the HTML in some other way before calling this, you may wish to set this to false to avoid the overhead.Boolean (defaults to true) – Should the HTML passed via calls to insertHTML be passed to the sanitizer? This includes when the user pastes from the clipboard. Since you cannot control what other apps put on the clipboard, it is highly recommended you do not set this to false.(html: String, isPaste: Boolean, self: Squire) -> DOMFragment
A custom sanitization function. This will be called instead of the default call to DOMPurify to sanitize the potentially dangerous HTML. It is passed three arguments: the first is the string of HTML, the second is a boolean indicating if this content has come from the clipboard, rather than an explicit call by your own code, the third 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.Squire provides an engine that handles the heavy work for you, making it easy to add extra features. With the changeFormat method you can easily add or remove any inline formatting you wish. And the modifyBlocks method can be used to make complicated block-level changes in a relatively easy manner.
If you load the library into a top-level document (rather than an iframe), or load it in an iframe without the data-squireinit="true" attribute on its <html> element, it will not turn the page into an editable document, but will instead add a constructor named Squire to the global scope.
You can also require the NPM package squire-rte to import Squire in a modular program without adding names to the global namespace.
Call new Squire( document ), with the document from an iframe to instantiate multiple rich text areas on the same page efficiently. Note, for compatibility with all browsers (particularly Firefox), you MUST wait for the iframe's onload event to fire before instantiating Squire.
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 document.execCommand 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.
By default, the editor will use a `
for blank lines, as most users have been conditioned by Microsoft Word to expect <kbd>Enter</kbd> to act like pressing <kbd>return</kbd> 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;' }
})
If using the simple setup, call editor.setConfig(…); with your
config object instead. Be sure to do this before calling editor.setHTML().
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 hasFormat method for each of your buttons to determine whether the styles are active. See the getPath and hasFormat documentation for more information.
Squire is released under the MIT license. See LICENSE for full license.
Attach an event listener to the editor. The handler can be either a function or an object with a handleEvent 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:
editor.getHTML() will have changed.path property on the event object.canUndo and canRedo to let you know the new state.fragment property on the event object, or the text property for plain text being inserted into a <pre>. You can modify this text/fragment in your event handler to change what will be pasted. You can also call the preventDefault on the event object to cancel the paste operation.The method takes two arguments:
Returns self (the Squire instance).
Remove an event listener attached via the addEventListener method.
The method takes two arguments:
Returns self (the Squire instance).
Adds or removes a keyboard shortcut. You can use this to override the default keyboard shortcuts (e.g. Ctrl-B for bold – see the bottom of KeyHandlers.js for the list).
This method takes two arguments:
"alt-ctrl-meta-shift-enter"null if removing a key handler. The function will be passed three arguments when called:Returns self (the Squire instance).
Focuses the editor.
The method takes no arguments.
Returns self (the Squire instance).
Removes focus from the editor.
The method takes no arguments.
Returns self (the Squire instance).
Returns the document object of the editable area. May be useful to do transformations outside the realm of the API.
Returns the HTML value of the editor in its current state. This value is equivalent to the contents of the <body> tag and does not include any surrounding boilerplate.
Sets the HTML value for the editor. The value supplied should not contain <body> tags or anything outside of that.
The method takes one argument:
Returns self (the Squire instance).
Returns the text currently selected in the editor.
Inserts an image at the current cursor location.
The method takes two arguments:
<img> node. e.g. { class: 'class-name' }. Any src attribute will be overwritten by the url given as the first argument.Returns a reference to the newly inserted image element.
Inserts an HTML fragment at the current cursor location, or replaces the selection if selected. The value supplied should not contain <body> tags or anything outside of that.
The method takes one argument:
Returns self (the Squire instance).
Returns the path through the DOM tree from the <body> element to the current current cursor position. This is a string consisting of the tag, id, class, font, and color names in CSS format. For example BODY>BLOCKQUOTE>DIV#id>STRONG>SPAN.font[fontFamily=Arial,sans-serif]>EM. If a selection has been made, so different parts of the selection may have different paths, the value will be (selection). The path is useful for efficiently determining the current formatting for bold, italic, underline etc, and thus determining button state. If a selection has been made, you can has the hasFormat method instead to get the current state for the properties you care about.
Returns an object containing the active
$ claude mcp add Squire \
-- python -m otcore.mcp_server <graph>