jamuny.editor

Local-firstYour text never leaves your browser. No upload, no account, no server.

What does "local-first" mean?

Most online text tools send whatever you paste to a server, run the work there, and send a result back. Your words sit in someone else's logs, backups and databases, and you have to trust a privacy policy.

Local-first means the opposite: the whole tool is downloaded to your browser and runs on your own device. Nothing you type is transmitted anywhere: not to us, not to anyone. There is no server that could receive it, which is a stronger guarantee than a promise not to look.

Three consequences worth knowing:

  • It keeps working offline. Once the page has loaded, losing your connection changes nothing.
  • Your notes are saved on this device only. They come back when you return, but they do not follow you to your phone, and clearing your browser data for this site erases them for good. Export anything you need to keep.
  • Nothing to sign up for or delete. There is no account, because there is no server holding anything of yours.

HTML Entity Encoder and Decoder

Turn characters into HTML entities so they display as text rather than being parsed as markup, or decode entities back into readable characters. Three encoding modes cover the usual needs: escaping only the five characters that change how HTML parses, using named entities where they exist, or escaping everything non-ASCII by codepoint for maximum compatibility. Emoji and astral characters survive intact rather than being split into broken surrogate halves.

How to use it

  1. Paste your text or HTML. Either content you want to escape, or entities you want to read.
  2. Choose a mode. Minimal escapes only the characters that affect parsing. Named and numeric also escape non-ASCII.
  3. Copy the result. Round trips are lossless, so decoding what you encoded returns exactly what you started with.

Worked example

The same input in each encoding mode

Input
<b>Café</b> & "quotes"
Output
Minimal: &lt;b&gt;Café&lt;/b&gt; &amp; &quot;quotes&quot;
Numeric: &lt;b&gt;Caf&#233;&lt;/b&gt; &amp; &quot;quotes&quot;

Only five characters actually matter

The ampersand, less-than, greater-than, double quote and apostrophe are the characters that can change how surrounding markup parses, by ending an attribute early, or opening a tag that was meant to be text. Everything else is a rendering preference.

Order matters when escaping them. The ampersand must be replaced first, because every other replacement introduces one: escape the less-than sign first and the &lt; you just produced becomes &amp;lt; on the next pass. Double-escaped output is a common bug and looks like the tool is broken when the real cause is sequence.

Escaping is not the same as being safe

HTML-escaping is the correct primitive for inserting untrusted text into a page, but where the text lands decides whether it is enough. Escaped text is safe as element content and inside a quoted attribute value. It is not sufficient inside a script block, inside a style block, or in an unquoted attribute, and it does nothing at all about a javascript: URL sitting in an href.

The practical advice is to let your templating layer escape at the point of insertion, where it knows the context, rather than pre-escaping strings and storing them escaped. Pre-escaped data has a habit of being escaped twice or displayed raw somewhere that did not expect it.

Named, numeric, and emoji

Named entities such as &copy; and &mdash; are readable in hand-edited source, which is their entire advantage. Numeric entities need no lookup table, cannot reference a name a parser does not recognise, and are the safer default for generated output. Both decode identically everywhere.

Emoji are where many tools quietly fail. An emoji occupies two UTF-16 code units internally, and a tool iterating by code unit escapes each half separately, producing two entities that no longer reassemble into anything. Iterating by codepoint, which is what happens here, keeps an emoji as one entity that round-trips exactly.

Questions

Which characters actually need escaping?

Five: the ampersand, less-than, greater-than, double quote and apostrophe. Those are the ones that can end an attribute or open a tag and so change how the surrounding markup parses. Everything else is a display concern rather than a correctness one, which is what the minimal mode escapes.

Does this prevent XSS?

Escaping is the right primitive, but where you insert the result matters just as much. HTML-escaped text is safe as element content and inside quoted attributes. It is not sufficient inside a script block, a style block, or an unquoted attribute, and it does nothing for a javascript: URL in an href. Use your framework's own escaping in templates rather than pre-escaping strings.

Named or numeric entities, which should I use?

Numeric is the safer default because it needs no lookup table and cannot hit an entity name a parser does not know. Named entities are more readable in source, so they suit hand-edited HTML. Both decode identically in every modern browser.

Why do other tools break on emoji?

Because they iterate the string by UTF-16 code unit rather than by character. An emoji occupies two code units, so escaping each one separately produces two entities that no longer reassemble. This iterates by codepoint, so an emoji becomes a single entity and round-trips exactly.