https://github.com/evolutionjobs/html-editor
Sandboxed HTML editor
https://github.com/evolutionjobs/html-editor
polymer rich-text-editor sandbox web-component
Last synced: 11 months ago
JSON representation
Sandboxed HTML editor
- Host: GitHub
- URL: https://github.com/evolutionjobs/html-editor
- Owner: EvolutionJobs
- License: mit
- Created: 2017-11-22T16:22:32.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2018-02-12T16:30:20.000Z (about 8 years ago)
- Last Synced: 2025-02-06T23:28:48.090Z (about 1 year ago)
- Topics: polymer, rich-text-editor, sandbox, web-component
- Language: HTML
- Size: 212 KB
- Stars: 0
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ``
This is a web-component, lightweight, bare bones HTML editor that wraps the HTML in an `` so that malicious scripts embedded in the HTML cannot execute in your page.
## Why another rich text editor?
I have a couple of restrictions:
* Must be compatible with web components and shadow DOM.
* Must handle a wide variety of possibly dodgy HTML.
* Should work when imported as a module or asychronously brought into the page.
* Should be open source.
Unfortunately those rule out every HTML editor component I've been able to find. Shadow DOM means libraries that rely on `document...` methods (like the otherwise excellent [Quill](https://github.com/quilljs/quill)) can't work. Those that do work are too easy to inject `` tags into, or need loading with the initial page, or rely on Regex to find XSS.
## How does it protect against XSS?
Like most HTML editors this uses `contenteditable` on the body of a new page in an `<iframe>` and [`document.execCommand`](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand) to provide functions like _Bold_ and _Italic_.
Where this differs is that the `<iframe>` is flagged with the [`sandbox="allow-scripts"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) attribute. This allows scripts to run inside the `<iframe>`, but in their own unique origin - they can't execute anything in the context of the page that contains it, they can't POST, they can't resend cookies (no CSRF), they can't display dialogs, and they can't get out of the frame.
The problem with this `sandbox` is that it isn't easy for the parent page and the frame to communicate any more. So this uses [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) is used to send content and commands.
So when a _Bold_ command is executed the wrapper component uses `postMessage` to sent that to the `<iframe>`, and then in that page it picks up the message and calls `document.execCommand`. When the user inputs changes to the `contenteditable` body that uses `postMessage` to sent the changed HTML back up to the containing page.
## How do I use it?
This component consists of two web components:
* `<sandbox-editor>` stand alone HTML editor sandbox with no UI
* `<html-editor>` Polymer 2 UI, which depends on HTML imports and further Polymer components.
### `<sandbox-editor>`
Include the script in your page:
<script type="module" src="{path}/html-editor/sandbox-editor.js">
Include the tag in your HTML:
The `content` attribute (it can also be set as a property) holds the HTML to set. `content-changed` fires when the user updates the HTML. This is compatible with [Polymer's `notify` properties](https://www.polymer-project.org/2.0/docs/devguide/properties), so you can use its two-way binding.
To execute commands against the editor call `editorAction`:
const sandbox = parentElement.querySelector('sandbox-editor');
sandbox.editorAction('bold'); // make the current selection bold
sandbox.editorAction('backColor', '#fdb5fb'); // make the background pink
For an example of this see the [source of ``](html-editor.html)
Finally, `` fires an event when the body inside the editor gains focus. This appears as the `focused` property and fires `focused-changed` when it changes.
### ``
Include the HTML import:
Include the tag in your HTML:
The `content` attribute (it can also be set as a property) holds the HTML to set, Polymer two-way databinding is supported.

You can add your own buttons if you want in the `slot`:
Maek Kustom Blod!
`` only shows the toolbar while the `` or some other control in the shadow DOM has focus.