Plugin: Copy as HTML [v1.1.6, 2025-08-24]

Joplin Copy as HTML Plugin :clipboard:

NOTE:
My coding knowledge is currently very limited. This plugin was created entirely with AI tools, and I may be limited in my ability to fix any issues.

I mainly created this plugin for myself, but I figured others may find it useful:

This plugin allows you to copy selected text in the markdown editor as either HTML or plain text (with markdown formatting characters removed).

The primary use case is copying text from Joplin and pasting formatted text into other apps that support HTML formatting (e.g. pasting text into an Outlook email). A plain text fallback is provided for scenarios where you need to paste text into an application that supports neither HTML formatting nor markdown.

Copy as HTML

"Copy selection as HTML" is provided as a right click context menu option and as a keyboard shortcut (ctrl + shift + c by default).

This will populate the clipboard's text/html category with the HTML formatted text.

Embed images as base64

By default, the plugin will embed any images as base64 in the text/html output, allowing you paste text + images into external applications. However, this can be disabled in the plugin's settings.

This should work with both markdown image embeds and the html <img> embeds that you get when resizing images via joplin's rich text editor.

Export as fragment or full HTML document

When you copy text from Joplin's markdown viewer (or export the note to HTML), there is a lot of styling applied which can sometimes cause issues pasting text into other editors (e.g. if you copy from the markdown viewer, your joplin theme's background color may be pasted).

HTML Fragment

By default, the plugin will populate the clipboard with an HTML fragment, e.g:

<html>
   <body>
      <!--StartFragment-->
      <h2>Test Heading</h2>
      <p>Test paragraph 1</p>
      <p>Test paragraph 2</p>
      <!--EndFragment-->
   </body>
</html>

This is similar to what you get when copying from Joplin's TinyMCE rich text editor (semantic markup, no css styling). Any styling will be determined by the application you're pasting the text into.

Full HTML Document

Optionally, you can enable the setting "Export as full HTML document".

This will wrap the HTML fragment in a full HTML document with CSS styling. A default (minimal) css stylesheet is provided. The default stylesheet is only used if no custom stylesheet is provided and the "Export as full HTML document" setting is enabled.

To use your own stylesheet, create a file called copy-as-html-user.css in your Joplin profile directory. To locate your Joplin profile directory, open Joplin and click Help | Open profile directory.

Optional markdown syntax

The plugin will adhere to Joplin's settings for whether or not to render:

  • Soft Breaks
  • Typographer
  • Linkify
  • ==mark==
  • Footnotes
  • Table of Contents
  • ~sub~
  • ^sup^
  • Deflist
  • Abbreviation
  • Markdown Emoji
  • ++Insert++
  • Multimarkdown Table

Copy as Plain Text

"Copy selection as Plain Text" is provided as a right click context menu option and as a keyboard shortcut (ctrl + alt + c by default).

This will strip markdown formatting characters, backslash escapes, and image embeds from the source markdown and populate it as text/plain in the clipboard, for scenarios where you need to paste into an app that supports neither HTML formatting or markdown.

List leaders and nested list indentation will be maintained (these are normally lost when copying from the markdown viewer or rich text editor).

Customizing plain text output

The following options are provided to preserve specific markdown formatting in the text/plain output:

  • Preserve superscript characters (^TEST^)

  • Preserve subscript characters (~TEST~)

  • Preserve emphasis characters (*TEST* or _TEST_)

  • Preserve bold characters (**TEST** or __TEST__)

  • Preserve heading characters (## TEST)

  • Preserve strikethrough characters (~~TEST~~)

  • Preserve horizontal rule (---)

  • Preserve highlight characters (==TEST==)

  • Preserve insert characters (++TEST++)

The following options are provided for external hyperlinks (only impacts markdown links containing http/https URL):

  • Title - Displays link title only (default).

  • URL - Displays link URL only.

  • Markdown Format - Displays full markdown link formatting with title and URL.

Markdown emoji

Copy as Plain Text supports the markdown-it emoji plugin, so emoji such as :white_check_mark: will be displayed in the plain text output. This can be disabled if desired via the Display emojis setting.

Known Issues

  • The context menu options appear in the rich text editor's context menu (but aren't functional, the plugin is only intended for the markdown editor).
  • The plugin's keyboard shortcuts sometimes don't work on cold start of Joplin, can be fixed by toggling editors or going to Tools | Options | Keyboard Shortcuts and back.
  • When using the "Full Document" mode for custom css styling, the full HTML document will be nested under another <html>/<body> in the clipboard. I don't think there's a way to fix this without having access to electron clipboard API. Nested html/body (while not technically valid HTML) is the best solution I found (doesn't seem to cause issues pasting into other apps and is the same thing that the obsidian copy document as html plugin does).
3 Likes

Changes from v1.0.3 to v1.0.6:

  • Replaced ugly error dialogue that appeared when you activated the plugin without any text selected with an info toast
  • Updated the copy successful toast message to use success toast type
  • Gracefully handle invalid resource links when embedding images. Now, the copy will still succeed and any invalid images will be replaced with placeholder text (Resource ID “:/resource-id-here” could not be found.)
  • Remove &nbsp; characters from text/plain output

v1.0.8

Significant changes to the copy as plaintext feature:

1. The plugin now uses markdown-it with a custom renderer to extract the plaintext instead of the remove-markdown package. This allows for much greater flexibility in customizing the plain text output.

2. The plugin now has several options to preserve a subset of markdown formatting in the plaintext output.

In my case, the main thing I care about in the plaintext output is getting rid of those damned backslash escape characters, I don't mind having the basic markdown formatting like bold, italics, etc... so there are now options to preserve these:

  • Preserve superscript characters (^TEST^)
    If enabled, ^TEST^ will remain ^TEST^ in plain text output.

  • Preserve subscript characters (~TEST~)
    If enabled, ~TEST~ will remain ~TEST~ in plain text output.

  • Preserve emphasis characters (*TEST* or _TEST_)
    If enabled, *TEST* or _TEST_ will remain as-is in plain text output.

  • Preserve bold characters (**TEST** or __TEST__)
    If enabled, **TEST** or __TEST__ will remain as-is in plain text output.

  • Preserve heading characters (## TEST)
    If enabled, ## TEST will remain as-is in plain text output.

3. Nicer tables. Instead of exporting the raw markdown table, you'll get a properly aligned table, e.g:

TestColumn1  TestColumn2  TestColumn3
-----------  -----------  -----------
A            B            C          
D            E            F          

3. Paragraph breaks are consistently maintained (e.g. below headings and below code blocks).

v1.0.9

  • [copy as plaintext] Fixed broken ordered list numbering when there were nested unordered lists between ordered list entries
  • [copy as plaintext] Maintain indentation of nested list items
1 Like

v1.0.11

  • [Copy as HTML] width/height properties are now preserved in the extracted HTML, so image sizes are retained when copying html <img> formatted images.
  • [Copy as Plain Text] - Removed logic to remove html <img> elements from the plain text output, it was causing various issues (and if your selection contains both text + images you probably want to copy as HTML anyway).
  • [Copy as Plain Text] regex for removing nbsp from plain text output was much too greedy, adjusted so it only removes nbsp if on its own line

v1.0.12

  • [Copy as Plain Text] Completely removed regex to remove nbsp... it's no longer needed with the markdown-it implementation (since nbsp is no longer shown as literal text in the text/plain output), and removing it allows us to maintain whitespace created by the rich text editor (nbsp on its own line)

v1.0.13

  • [Copy as Plain Text] Restored functionality to remove html <img> embeds from text/plain output, now works without touching code blocks using the same method that was used for removing backslash escapes

v1.0.14

  • [Copy as Plain Text] don't collapse whitespace inside code blocks
1 Like

Thanks for this plugin :+1:

v1.0.15

  • [Copy as Plain Text] New Feature: Add setting for hyperlink behavior (Link Title, URL, or Markdown format)
  • No other user facing changes, code was significantly cleaned up and refactored

v1.0.16

  • [Copy as Plain Text] Fix space below block quotes
  • No other user facing changes, code was significantly re-factored (split into multiple files, implement type safety throughout, improve error handling, add input and configuration validation)

v1.0.18

  • [Copy as HTML] - fix spacing issues with indented block elements followed by horizontal rules
  • [Copy as HTML] - remove joplin specific onclick markup from final html fragment
  • [Copy as Plain Text] - also handle ++insert++ and ==mark== in plaintext output
  • More code refactoring and cleanup, improved error handling

I'll chill out with the rapid updates for now :D, I think the plugin is in a good state

2 Likes

Thank you for this great and useful plugin. But, I’ve got a problem. It is a general problem, not just here. I’m using Windows and Essential Pim for email also Windows. Windows uses a cr and a LF at the end of lines. when I paste, the html I get 2 lines between each paragraph or whenever there is a single line break. This happens a lot, not only with your plugin.

Does anyone know a way to handle this?

Does it only happen when pasting into the EssentialPIM app?

The behavior of pasting formatted text can vary quite a bit depending on the application you're pasting into. I mainly test the plugin with Gmail and Outlook and haven't seen any issues with extra line spacing when pasting.

The plugin currently generates just a semantic HTML fragment, e.g:

<html>
   <body>
      <!--StartFragment-->
      <h2 id="test-heading">Test Heading</h2>
      <p>Test paragraph 1</p>
      <p>Test paragraph 2</p>
      <!--EndFragment-->
   </body>
</html>

There is no styling provided, so any paragraph spacing, etc... should be controlled by the app you're pasting into (and this is most likely some kind of quirk with the essentialPIM app).

In an upcoming update, I'm adding support for the plugin to generate a full HTML document with a user supplied stylesheet, which could allow you to set specific paragraph spacing with CSS which might potentially help.

However, if essentialPIM is generating actual line breaks (<br>) when pasting, then css styling might not change the behavior.

You could try using the plugin's "Copy as Plain Text" option to copy the plain text- that would likely paste without any odd behavior (but you would lose any rich text formatting).

I did some testing, not much but some. Windows 11

I used 1. Windows built-in notepad
2. Notepad ++

3. and EPIM.

Copied a joplin note with some headers and lists and a bold face.

To EPIM

If I copy as html, it copies into epim with the extra blank lines. All formatting correct.

If I copy as plain text, then there is no formatting and no extra blank lines.

So it seems that there is a problem with my clipboard and how your copy as html handles the clipboard. Of the three programs, only epim recognizes that there exists anything to paste using that.

If I copy as html into notepad though I get a notice saying I have copied to HTML, nothing pastes at all. There is nothing in the clipboard I can find. Copy as plain text works as expected. Plain copy works as expected.

If I copy into notepad++

plain copy works fine (windows ctrl-c and ctrl-v)

copy as HTML does nothing. No copy. nothing in clipboard

copy as plain text works

yeah copying to HTML and then pasting as plain text doesn't work with the plugin currently,

Commonly when you copy formatted text from a web browser or rich text editor, the clipboard will be populated with both the text/html clipboard category (HTML formatted text) and the text/plain clipboard category (plain text).

This makes it so that if you paste into an app that supports rich text, the app knows to use text/html and paste the formatted text

And if you paste into an app that only supports plaintext (e.g. notepad), it pastes the contents of the text/plain category instead.

There's also a shortcut supported by most apps (ctrl + shift + v) to force pasting the text/plain instead of text/html

This is what I originally wanted to do with this plugin, but I ran into an issue which (I think, not 100% sure) is a limitation with the Joplin plugin API:

If you try to write both html and text to the clipboard at the same time ( using joplin.clipboard.writeHtml() and joplin.clipboard.writeText() ), you only get the HTML in the clipboard, so I resorted to making them separate commands ("Copy selection as HTML" and "Copy selection as Plain Text").

I might revisit that in the future, I would love it if I could get that to work as it's more intuitive/standard behavior.

I frequently have the same problem with extra blank lines when I copy parts of webpages or AI answers from various AI bots.

FYI—I tried copying directly into LibreOffice Writer, and it worked perfectly. However, the issue with extra blank lines in my email part of EssentialPIM occurs not only with your app but frequently with chatbots and selections from web pages. I’ll make a feature request to have an option that removes extra blank lines, perhaps functioning as a search and replace. However, I don’t even get a source code for what actually gets inserted into my email after the paste operation.

v1.1.0

This is a pretty big release! at this point I've been able to implement every feature that I originally set out to (and more):

Copy as HTML

Copy as Full Document

The plugin now allows you to copy as a full HTML document with your own custom CSS styling

A default (minimal) css stylesheet is provided. The default stylesheet is automatically used if no custom stylesheet is provided and the "Export as full HTML document" setting is enabled.

To use your own stylesheet, create a file called copy-as-html-user.css in your Joplin profile directory. To locate your Joplin profile directory, open Joplin and click Help | Open profile directory.

Settings adherence

When Copying to HTML, elements that are rendered now adhere to nearly every setting from Joplin's Markdown tab (basically, math and diagrams are the only things not supported):

  • Soft Breaks
  • Typographer (you can thank this plugin for making me go down this rabbit hole xD)
  • Linkify
  • ==mark==
  • Footnotes
  • Table of Contents
  • ~sub~
  • ^sup^
  • Deflist
  • Abbreviation
  • Markdown Emoji
  • ++Insert++
  • Multimarkdown Table

Other Changes

  • (non-image) Joplin Resource links will now only display the link title.

Copy as Plain Text

  • Setting to display markdown emojis. Emoji shortcodes will be completely hidden if disabled, or Emoji unicode characters will be displayed if enabled (default).

  • Setting to preserve horizontal rule. Also, there will now be whitespace where the horizontal rule was if not preserving them.
  • Setting to preserve strikethrough (it was pretty much the only bit of common mark formatting missing, so why not lol)

v1.1.1 - v1.1.6

  • [Copy as HTML] - Fix Edge case where <img> wasn't removed when image embedding was disabled
  • [Copy as HTML] - Configure Linkify so it only linkifies http(s) URLs and mailto links
  • [Copy as HTML] - Fix potential memory leak
  • [Copy as HTML] - Improved font stack in default stylesheet
  • [Copy as HTML] - Remove no longer used @joplin/renderer dependency to reduce plugin size
  • [Copy as HTML/Copy as Plain Text] Improve messaging when plugin is invoked from rich text editor
  • [Copy as Plain Text] - Feature: Add setting for Tabs or (4) Spaces for Indentation
  • [Copy as Plain Text] - Small reliability improvements