# How the Markdown Here Wrapper System Stores Original Markdown for Reverting Back to Source

> Discover how the wrapper system stores original Markdown using Base64 encoding in a hidden div's title attribute, enabling seamless reversion to source text.

- Repository: [Adam Pritchard/markdown-here](https://github.com/adam-p/markdown-here)
- Tags: internals
- Published: 2026-03-05

---

**The wrapper system stores the original Markdown by Base‑64‑encoding it and placing the encoded string inside a hidden `<div>` element’s `title` attribute, which is then nested inside the visible wrapper; reverting simply decodes that attribute and replaces the wrapper with the decoded text.**

The **adam‑p/markdown‑here** extension converts a user’s plain‑text Markdown selection into rich HTML, but it must also guarantee a loss‑less way to return to the source. To achieve this, the code in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js) implements a dual‑layer storage mechanism that embeds the original Markdown directly inside the rendered output while keeping it invisible to the reader.

## The Wrapper Architecture: A Dual‑Layer Storage Approach

When the user triggers the “Markdown Toggle” command, the extension builds a **wrapper element** that contains two distinct parts:

1. **The visible rendered HTML** – the Markdown converted to HTML via the `marked` parser.
2. **The hidden raw‑Markdown holder** – a child `<div>` that carries the original source in a `title` attribute.

This architecture ensures that the original Markdown travels with the rendered content wherever it is pasted (email clients, web forms, etc.) and can be recovered even if the page is saved and reopened later.

## Encoding and Storing the Original Source

### Base64 Encoding in the Title Attribute

Before the wrapper is inserted, the extension encodes the raw Markdown string using the browser’s `btoa` function. The resulting Base‑64 string is prefixed with `"MDH:"` and assigned to the `title` attribute of the hidden holder. This prefix acts as a magic signature that the revert logic looks for later.

The relevant construction code (lines 483‑492 in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js)) looks like this:

```javascript
// Wrap our pretty HTML in a <div> wrapper.
// We'll use the wrapper as a marker to indicate that we're in a rendered state.
wrapperHtml = '<div class="markdown-here-wrapper" ' +
              'data-md-url="' + url + '">' +
              mdHtml +                     // the visible rendered HTML
              '<div title="MDH:' + b64Md + // hidden holder with encoded original
              '" style="height:0;width:0;max-height:0;max-width:0;' +
              'overflow:hidden;font-size:0em;padding:0;margin:0;"></div>' +
              '</div>';

```

### The Hidden Holder Element

The child `<div>` is styled to be completely invisible:

* **Zero dimensions** – `height:0;width:0;max-height:0;max-width:0;`
* **Hidden overflow** – `overflow:hidden;`
* **Zero font size and spacing** – `font-size:0em;padding:0;margin:0;`

Because the element is part of the DOM, it survives copy‑paste operations into rich‑text editors and can be retrieved later by the same extension (or by any tool that knows to look for the `MDH:` prefix).

## Retrieving the Original Markdown for Reversion

### Locating the Raw Holder

When the user toggles back to Markdown, the extension calls `findElemRawHolder(wrapperElem)` (lines 471‑475 in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js)). This helper uses a CSS attribute selector to locate the hidden child:

```javascript
function findElemRawHolder(elem) {
    // Looks for a valid raw‑MD‑holder element under `elem`.
    // Only MDH wrappers will have a child <div> with a title that starts with "MDH:".
    var rawHolder = elem.querySelector('div[title^="MDH:"]');
    return rawHolder;
}

```

### Decoding and Restoring the Source

Once the holder is found, the `unrenderMarkdown` function (lines 519‑534) performs the actual restoration:

```javascript
function unrenderMarkdown(wrapperElem) {
    var rawHolder = findElemRawHolder(wrapperElem);
    if (!rawHolder) { return; }

    // The title stores “MDH:<base64‑encoded‑markdown>”.
    var b64 = rawHolder.title.substring(4); // strip the "MDH:" prefix
    var originalMdHtml = atob(b64);         // decode Base‑64 back to plain text

    // Replace the whole wrapper with its original Markdown.
    Utils.saferSetOuterHTML(wrapperElem, originalMdHtml);
}

```

The `Utils.saferSetOuterHTML` helper (defined in [`src/common/utils.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/utils.js)) ensures that the replacement happens without triggering unwanted side‑effects in the host page.

## Tracking Content Modifications

To prevent accidental data loss, the extension monitors the rendered content for edits. When the wrapper is first created, a `MutationObserver` watches for changes. If the user modifies the HTML, the wrapper receives the boolean attribute `markdown-here-wrapper-content-modified` (set around line 511 in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js)). Before reverting, the code checks this flag and warns the user that the original Markdown will overwrite their edits.

## Summary

* **Dual‑layer wrapper** – A visible `<div class="markdown-here-wrapper">` contains the rendered HTML plus a hidden child element.
* **Base‑64 encoding** – The original Markdown is encoded with `btoa`, prefixed with `"MDH:"`, and stored in the hidden child’s `title` attribute.
* **Invisible holder** – CSS zero‑sizing (`height:0;width:0;…`) keeps the holder out of sight while keeping it in the DOM.
* **Reversion logic** – `findElemRawHolder` locates the holder, `unrenderMarkdown` strips the prefix, decodes with `atob`, and replaces the wrapper via `Utils.saferSetOuterHTML`.
* **Edit detection** – The `markdown-here-wrapper-content-modified` attribute warns users before overwriting manual edits.

## Frequently Asked Questions

### How does the extension know which element contains the original Markdown?

The code looks for a child `<div>` whose `title` attribute begins with the literal string `"MDH:"`. This is performed by the `findElemRawHolder` helper in [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/markdown-here.js). Only wrappers created by the extension contain such an element, so the search is both precise and fast.

### What happens if I edit the rendered HTML before toggling back?

If you modify the rendered content, a `MutationObserver` detects the change and sets the boolean attribute `markdown-here-wrapper-content-modified` on the wrapper. When you later attempt to revert, the extension checks this flag and displays a confirmation dialog warning that your edits will be lost. This safety mechanism prevents accidental data loss while still allowing intentional reversion.

### Is the original Markdown stored securely?

The original Markdown is **not encrypted**; it is simply Base‑64‑encoded to ensure it survives transport through rich‑text editors that might otherwise strip newlines or special characters. Anyone with access to the DOM can decode the `title` attribute (e.g., via `atob` in the browser console). Therefore, you should not use Markdown Here to protect sensitive information; treat the stored source as plain text that happens to be obfuscated, not secured.

### Can I revert Markdown that was rendered on a different machine or browser?

Yes—provided the rendered HTML (including the hidden holder) was copied or saved intact. Because the original Markdown travels inside the `title` attribute of the hidden `<div>`, it survives copy‑paste operations into emails, documents, or web forms. When you later open that content in a browser with the Markdown Here extension installed, the wrapper is recognized, the `MDH:` prefix is detected, and the extension can decode and restore the original Markdown exactly as it was before rendering.