# adam-p/markdown-here architecture

> Architecture diagram of the GitHub repository adam-p/markdown-here, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-19). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/adam-p/markdown-here
- Repository: https://github.com/adam-p/markdown-here

## Overview

1. **What this repository is**
   - Markdown Here is a client-side browser/email extension, not a server app.
   - Its core job is to take Markdown typed in an email composer or other rich-text editor, render it to HTML, and later revert it back to Markdown if needed.

2. **Top-level runtime boundaries**
   - The extension is built from `src/manifest.json` plus browser-specific code under `src/chrome/`.
   - It targets multiple extension hosts: Chrome/Opera, Firefox, and Thunderbird.
   - The architecture is split between a long-lived **background page/script** and an injected **content script** that runs inside the host page/editor.

3. **Host-page integration layer**
   - `src/chrome/contentscript.js` is the bridge into Gmail/Hotmail/Yahoo/Google Groups/Thunderbird compose surfaces.
   - This layer is responsible for detecting editable regions, reading the user’s selection, and applying conversion results back into the page DOM.
   - `src/common/content-permissions.js` and related logic define which page contexts are eligible for conversion.

4. **Extension-level orchestration**
   - `src/chrome/backgroundscript.js` coordinates extension-wide behavior such as command handling, menu/button actions, and interaction with the content script.
   - `background.html` is the browser extension runtime container for that logic.
   - The background layer is where the extension can manage cross-page state without being tied to one editor instance.

5. **Markdown render / revert pipeline**
   - The main transformation logic lives in `src/common/markdown-here.js` and `src/common/markdown-render.js`.
   - Input starts as user-authored Markdown in the compose DOM, then is converted to HTML, styled, and inserted back into the editor.
   - Reversion is supported by keeping enough structure to map rendered blocks back to original Markdown, with HTML-to-text helpers in `mdh-html-to-text.js` and `jsHtmlToText.js`.

6. **Parsing and formatting dependencies**
   - Markdown parsing uses vendored `marked.js`.
   - Syntax highlighting uses vendored `highlightjs/highlight.js` plus a large set of theme CSS files in `src/common/highlightjs/styles/`.
   - This means rendering is fully client-side and bundled into the extension, with no external rendering service.

7. **Shared utility and configuration layer**
   - `src/common/common-logic.js`, `utils.js`, and `options-store.js` hold reusable logic shared by background, content, and options pages.
   - `src/common/default.css` is the base styling applied to rendered output.
   - `options-store.js` is the persistence boundary for user preferences such as styling, highlighting theme, TeX/math behavior, and hotkeys.

8. **Options and user customization surfaces**
   - `src/common/options.html`, `options.js`, and `options-iframe.*` implement the preferences UI.
   - The options surface is separate from the compose-page conversion flow and is used to configure rendering behavior, theme selection, and keyboard shortcuts.
   - The README notes browser sync support for Chrome/Firefox, so preference state is designed to be portable across installations of the same browser.

9. **UX helpers and secondary dialogs**
   - `src/common/forgot-to-render-prompt.html` provides a reminder flow when users try to send without converting.
   - `src/chrome/upgrade-notification-popup.html/js` handles version upgrade messaging.
   - These are auxiliary UI paths, not part of the main Markdown transformation pipeline, but they support adoption and error prevention.

10. **Internationalization and packaging**
   - `src/_locales/*` contains localized strings and description/caption assets for multiple languages.
   - `utils/build.js` packages the extension for release, and the README describes zipping `manifest.json`, `common/`, `chrome/`, and `_locales/` for WebExtension distribution.
   - `store-assets/` holds marketplace graphics/text, which are deployment assets rather than runtime code.

11. **Testing structure**
   - `src/common/test/` contains unit tests for the rendering, Markdown conversion, options store, and utility logic.
   - `test/` is a higher-level test harness entry point.
   - The tests focus on the shared conversion logic rather than browser-specific UI, which reflects the architecture: most correctness lives in the common rendering core.

12. **Overall data flow**
   - User types Markdown in a rich editor → content script captures the selection or document region → shared rendering logic converts Markdown to HTML with styling/highlighting → DOM is updated in place → optional revert path converts the rendered block back to Markdown.
   - The background script and options store sit beside that flow, providing commands, settings, and extension-wide coordination, but not doing the actual document transformation.

Main entry points: [`src/manifest.json`](https://github.com/adam-p/markdown-here/blob/master/src/manifest.json) (Manifest), [`src/chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/master/src/chrome/contentscript.js) (Content script), [`src/chrome/backgroundscript.js`](https://github.com/adam-p/markdown-here/blob/master/src/chrome/backgroundscript.js) (Background script), [`src/common/markdown-here.js`](https://github.com/adam-p/markdown-here/blob/master/src/common/markdown-here.js) (Markdown Here)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Extension runtime"]
  node_manifest["Manifest<br/>[manifest.json]"]
  node_bg_html["Background page<br/>runtime container<br/>[background.html]"]
  node_bg_script["Background script<br/>orchestrator"]
  node_content_script["Content script<br/>page bridge<br/>[contentscript.js]"]
  node_permissions["Page rules<br/>eligibility rules"]
end

subgraph group_rendering["Markdown pipeline"]
  node_md_here["Markdown Here<br/>render coordinator<br/>[markdown-here.js]"]
  node_md_render["Render core<br/>markdown renderer<br/>[markdown-render.js]"]
  node_marked["Markdown parser<br/>vendored parser<br/>[marked.js]"]
  node_highlight["Syntax highlighter<br/>vendored highlighter<br/>[highlight.js]"]
  node_styles["Theme styles<br/>style bundle<br/>[styles.json]"]
  node_html_text["HTML to text<br/>revert helpers"]
  node_js_text["Text helpers<br/>utility converter<br/>[jsHtmlToText.js]"]
end

subgraph group_ui["Preferences and dialogs"]
  node_common_logic["Shared logic<br/>shared utilities<br/>[common-logic.js]"]
  node_options_store[("Options store<br/>preference storage<br/>[options-store.js]")]
  node_options_ui["Options page<br/>preferences UI<br/>[options.html]"]
  node_options_js["Options logic<br/>ui controller<br/>[options.js]"]
  node_prompt["Send prompt<br/>auxiliary dialog"]
  node_upgrade["Upgrade notice<br/>auxiliary dialog"]
end

subgraph group_support["Packaging and assets"]
  node_locales["Locales<br/>i18n assets"]
  node_build["Build tool<br/>packaging script<br/>[build.js]"]
  node_tests["Test harness<br/>test entrypoint<br/>[index.html]"]
end

node_manifest -->|"loads"| node_bg_html
node_manifest -->|"injects"| node_content_script
node_manifest -->|"opens"| node_options_ui
node_manifest -->|"localizes"| node_locales
node_bg_html -->|"hosts"| node_bg_script
node_bg_script -->|"commands"| node_content_script
node_content_script -->|"checks"| node_permissions
node_content_script -->|"converts"| node_md_here
node_md_here -->|"calls"| node_md_render
node_md_render -->|"parses"| node_marked
node_md_render -->|"highlights"| node_highlight
node_highlight -->|"themes"| node_styles
node_md_here -->|"reverts"| node_html_text
node_html_text -->|"uses"| node_js_text
node_options_ui -->|"drives"| node_options_js
node_options_js -->|"persists"| node_options_store
node_options_js -->|"shares"| node_common_logic
node_content_script -->|"shares"| node_common_logic
node_bg_script -->|"shares"| node_common_logic
node_prompt -->|"warns"| node_md_here
node_upgrade -->|"notifies"| node_bg_script
node_build -->|"packages"| node_manifest
node_tests -->|"verifies"| node_md_render
node_tests -->|"verifies"| node_options_store

click node_manifest "https://github.com/adam-p/markdown-here/blob/master/src/manifest.json"
click node_bg_html "https://github.com/adam-p/markdown-here/blob/master/src/chrome/background.html"
click node_bg_script "https://github.com/adam-p/markdown-here/blob/master/src/chrome/backgroundscript.js"
click node_content_script "https://github.com/adam-p/markdown-here/blob/master/src/chrome/contentscript.js"
click node_permissions "https://github.com/adam-p/markdown-here/blob/master/src/common/content-permissions.js"
click node_md_here "https://github.com/adam-p/markdown-here/blob/master/src/common/markdown-here.js"
click node_md_render "https://github.com/adam-p/markdown-here/blob/master/src/common/markdown-render.js"
click node_marked "https://github.com/adam-p/markdown-here/blob/master/src/common/marked.js"
click node_highlight "https://github.com/adam-p/markdown-here/blob/master/src/common/highlightjs/highlight.js"
click node_styles "https://github.com/adam-p/markdown-here/blob/master/src/common/highlightjs/styles/styles.json"
click node_html_text "https://github.com/adam-p/markdown-here/blob/master/src/common/mdh-html-to-text.js"
click node_js_text "https://github.com/adam-p/markdown-here/blob/master/src/common/jsHtmlToText.js"
click node_common_logic "https://github.com/adam-p/markdown-here/blob/master/src/common/common-logic.js"
click node_options_store "https://github.com/adam-p/markdown-here/blob/master/src/common/options-store.js"
click node_options_ui "https://github.com/adam-p/markdown-here/blob/master/src/common/options.html"
click node_options_js "https://github.com/adam-p/markdown-here/blob/master/src/common/options.js"
click node_prompt "https://github.com/adam-p/markdown-here/blob/master/src/common/forgot-to-render-prompt.html"
click node_upgrade "https://github.com/adam-p/markdown-here/blob/master/src/chrome/upgrade-notification-popup.html"
click node_locales "https://github.com/adam-p/markdown-here/tree/master/src/_locales"
click node_build "https://github.com/adam-p/markdown-here/blob/master/utils/build.js"
click node_tests "https://github.com/adam-p/markdown-here/blob/master/test/index.html"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_manifest,node_bg_html,node_bg_script,node_content_script,node_permissions toneBlue
class node_md_here,node_md_render,node_marked,node_highlight,node_styles,node_html_text,node_js_text toneAmber
class node_common_logic,node_options_store,node_options_ui,node_options_js,node_prompt,node_upgrade toneMint
class node_locales,node_build,node_tests toneRose
```

## Components

### Extension runtime

Browser extension entrypoints and page integration.

- [Manifest](https://github.com/adam-p/markdown-here/blob/master/src/manifest.json): extension manifest · Declares extension entrypoints and permissions. · `src/manifest.json`
- [Background page](https://github.com/adam-p/markdown-here/blob/master/src/chrome/background.html): runtime container · Extension host page for background logic. · `src/chrome/background.html`
- [Background script](https://github.com/adam-p/markdown-here/blob/master/src/chrome/backgroundscript.js): orchestrator · Coordinates commands, menus, and cross-page state. · `src/chrome/backgroundscript.js`
- [Content script](https://github.com/adam-p/markdown-here/blob/master/src/chrome/contentscript.js): page bridge · Injects into compose surfaces and applies conversions in-page. · `src/chrome/contentscript.js`
- [Page rules](https://github.com/adam-p/markdown-here/blob/master/src/common/content-permissions.js): eligibility rules · Determines which host pages and editors can be converted. · `src/common/content-permissions.js`

### Markdown pipeline

Shared conversion, parsing, and revert logic.

- [Markdown Here](https://github.com/adam-p/markdown-here/blob/master/src/common/markdown-here.js): render coordinator · Main conversion entrypoint used by the extension. · `src/common/markdown-here.js`
- [Render core](https://github.com/adam-p/markdown-here/blob/master/src/common/markdown-render.js): markdown renderer · Transforms Markdown into styled HTML for insertion. · `src/common/markdown-render.js`
- [Markdown parser](https://github.com/adam-p/markdown-here/blob/master/src/common/marked.js): vendored parser · Bundled Markdown parsing dependency. · `src/common/marked.js`
- [Syntax highlighter](https://github.com/adam-p/markdown-here/blob/master/src/common/highlightjs/highlight.js): vendored highlighter · Bundled code highlighting engine. · `src/common/highlightjs/highlight.js`
- [Theme styles](https://github.com/adam-p/markdown-here/blob/master/src/common/highlightjs/styles/styles.json): style bundle · Highlight.js theme CSS collection used by rendered output. · `src/common/highlightjs/styles/styles.json`
- [HTML to text](https://github.com/adam-p/markdown-here/blob/master/src/common/mdh-html-to-text.js): revert helpers · Helpers for mapping rendered HTML back to Markdown text. · `src/common/mdh-html-to-text.js`
- [Text helpers](https://github.com/adam-p/markdown-here/blob/master/src/common/jsHtmlToText.js): utility converter · Generic HTML/text conversion helpers used in revert flows. · `src/common/jsHtmlToText.js`

### Preferences and dialogs

Settings and auxiliary user-facing pages.

- [Shared logic](https://github.com/adam-p/markdown-here/blob/master/src/common/common-logic.js): shared utilities · Reusable logic shared by background, content, and options pages. · `src/common/common-logic.js`
- [Options store](https://github.com/adam-p/markdown-here/blob/master/src/common/options-store.js): preference storage · Persists rendering, theme, TeX, and hotkey settings. · `src/common/options-store.js`
- [Options page](https://github.com/adam-p/markdown-here/blob/master/src/common/options.html): preferences UI · Main settings page for user customization. · `src/common/options.html`
- [Options logic](https://github.com/adam-p/markdown-here/blob/master/src/common/options.js): ui controller · Drives the preferences interface and sync behavior. · `src/common/options.js`
- [Send prompt](https://github.com/adam-p/markdown-here/blob/master/src/common/forgot-to-render-prompt.html): auxiliary dialog · Reminder flow for users who forget to render before sending. · `src/common/forgot-to-render-prompt.html`
- [Upgrade notice](https://github.com/adam-p/markdown-here/blob/master/src/chrome/upgrade-notification-popup.html): auxiliary dialog · Version upgrade notification popup. · `src/chrome/upgrade-notification-popup.html`

### Packaging and assets

Locales, build tooling, and release assets.

- [Locales](https://github.com/adam-p/markdown-here/tree/master/src/_locales): i18n assets · Localized strings and captions for supported languages. · `src/_locales`
- [Build tool](https://github.com/adam-p/markdown-here/blob/master/utils/build.js): packaging script · Packages the extension for release distribution. · `utils/build.js`
- [Test harness](https://github.com/adam-p/markdown-here/blob/master/test/index.html): test entrypoint · Runs repository tests focused on shared logic. · `test/index.html`

## Connections

- Manifest → Background page: loads · Manifest declares the background runtime container.
- Manifest → Content script: injects · Manifest installs the content script into eligible pages.
- Manifest → Options page: opens · Manifest exposes the options page entry.
- Manifest → Locales: localizes · Manifest references localized strings.
- Background page → Background script: hosts · Background page runs the extension orchestration script.
- Background script → Content script: commands · Background script coordinates actions with injected pages.
- Content script → Page rules: checks · Content logic filters eligible editor contexts.
- Content script → Markdown Here: converts · Bridge invokes the shared Markdown conversion flow.
- Markdown Here → Render core: calls · Coordinator delegates transformation work to render core.
- Render core → Markdown parser: parses · Render core uses the vendored Markdown parser.
- Render core → Syntax highlighter: highlights · Render core applies syntax highlighting.
- Syntax highlighter → Theme styles: themes · Highlighter is paired with theme CSS assets.
- Markdown Here → HTML to text: reverts · Rendered blocks can be mapped back to Markdown.
- HTML to text → Text helpers: uses · HTML/text conversion helpers support reversion.
- Options page → Options logic: drives · Options page UI is controlled by its script.
- Options logic → Options store: persists · Preferences are read from and written to storage.
- Options logic → Shared logic: shares · Options logic reuses shared application helpers.
- Content script → Shared logic: shares · Content script reuses shared application helpers.
- Background script → Shared logic: shares · Background script reuses shared application helpers.
- Send prompt → Markdown Here: warns · Reminder dialog steers users back to rendering.
- Upgrade notice → Background script: notifies · Upgrade popup is tied to extension-wide version handling.
- Build tool → Manifest: packages · Build tooling bundles the extension manifest and assets.
- Test harness → Render core: verifies · Test harness exercises shared rendering behavior.
- Test harness → Options store: verifies · Tests cover preference storage behavior.
