Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save GitMurf/ec35c81003b172ce01044993d9849505 to your computer and use it in GitHub Desktop.
Save GitMurf/ec35c81003b172ce01044993d9849505 to your computer and use it in GitHub Desktop.
<%*
const editor = app.workspace.activeLeaf.view.editor;
if(editor.somethingSelected() === true) {
let selectedText = editor.getSelection();
let splitLines = selectedText.split('\n');
let finalOutput = '';
let listItem = false;
let codeBlock = false;
splitLines.forEach(eachLine => {
let lnOutput = eachLine;
const listMatch = lnOutput.match(/^[ \t]*[\-\*] /);
if(listItem === false) {
if(listMatch) {
listItem = true;
finalOutput = `${finalOutput}<ul>`;
}
} else {
if(!listMatch) {
listItem = false;
finalOutput = `${finalOutput}</ul>`;
}
}
//remove tags
lnOutput = lnOutput.replace(/#[^\s\#]+/g, '');
//replace a [ ] task checkbox
lnOutput = lnOutput.replace(/\[ \]/g, '<span style="background-color: #FFFF00"><strong>ACTION ITEM:</strong></span>');
//Parse out alias from wiki links
lnOutput = lnOutput.replace(/\[\[[^\[\]]+\|([^\[\]]+)\]\]/g, '$1');
//Parse out regular wiki bracket links
lnOutput = lnOutput.replace(/\[\[([^\[\]]+)\]\]/g, '$1');
//Parse out markdown style URLs
lnOutput = lnOutput.replace(/\[([^\[\]]*)\]\(([^ ]+)\)/g, '<a href="$2">$1</a>');
//Bold asterisk
lnOutput = lnOutput.replace(/\*\*([^\*]+)\*\*/g, '<strong>$1</strong>');
//Bold underscore
lnOutput = lnOutput.replace(/\_\_([^\_]+)\_\_/g, '<strong>$1</strong>');
//Italics asterisk
lnOutput = lnOutput.replace(/\*([^\*]+)\*/g, '<em>$1</em>');
//Italics underscore
lnOutput = lnOutput.replace(/\_([^\_]+)\_/g, '<em>$1</em>');
//Highlights
lnOutput = lnOutput.replace(/\=\=([^\=]+)\=\=/g, '<span style="background-color: #FFFF00">$1</span>');
//Strikethrough
lnOutput = lnOutput.replace(/\~\~([^\~]+)\~\~/g, '<strike>$1</strike>');
//Inline code
let backTickChar = "`";
let regExpStr = `${backTickChar}+([^${backTickChar}]+)${backTickChar}+`;
let regReplace = new RegExp(regExpStr, "g");
lnOutput = lnOutput.replace(regReplace, '<code>$1</code>');
//Full code blocks
if(lnOutput.indexOf("```") > -1) {
let backTickChar = "`";
let regExpStr = `${backTickChar}+[^${backTickChar}]*`;
let regReplace = new RegExp(regExpStr, "g");
if(codeBlock === false) {
codeBlock = true;
lnOutput = lnOutput.replace(regReplace, '<code>');
} else {
codeBlock = false;
lnOutput = lnOutput.replace(regReplace, '</code>');
}
}
//HEADERS
//H1
lnOutput = lnOutput.replace(/^\# (.*)/, '<h1>$1</h1>');
//H2
lnOutput = lnOutput.replace(/^\## (.*)/, '<h2>$1</h2>');
//H3
lnOutput = lnOutput.replace(/^\### (.*)/, '<h3>$1</h3>');
//H4
lnOutput = lnOutput.replace(/^\#### (.*)/, '<h4>$1</h4>');
//H5
lnOutput = lnOutput.replace(/^\##### (.*)/, '<h5>$1</h5>');
//H6
lnOutput = lnOutput.replace(/^\###### (.*)/, '<h6>$1</h6>');
//Remove extra whitespace
lnOutput = lnOutput.replace(/(\S)[ ]+/g, '$1 ');
//Formatting for paste into tools like Microsoft Word, OneNote, Outlook to match their bullet styles
lnOutput = lnOutput.replace(/^[\-\*] (.*)/, '<li>$1</li>');
lnOutput = lnOutput.replace(/^( |\t)[\-\*] (.*)/, '<ul><li>$2</li></ul>');
lnOutput = lnOutput.replace(/^( |\t\t)[\-\*] (.*)/, '<ul><ul><li>$2</li></ul></ul>');
lnOutput = lnOutput.replace(/^( |\t\t\t)[\-\*] (.*)/, '<ul><ul><ul><li>$2</li></ul></ul></ul>');
lnOutput = lnOutput.replace(/^( |\t\t\t\t)[\-\*] (.*)/, '<ul><ul><ul><ul><li>$2</li></ul></ul></ul></ul>');
lnOutput = lnOutput.replace(/^( |\t\t\t\t\t)[\-\*] (.*)/, '<ul><ul><ul><ul><ul><li>$2</li></ul></ul></ul></ul></ul>');
if(listItem === false) {
finalOutput = `${finalOutput}<br>${lnOutput}`
} else {
finalOutput = `${finalOutput}${lnOutput}`
}
})
if(listItem === true) {
finalOutput = `${finalOutput}</ul>`;
}
let newString = finalOutput.trim();
newString = newString.replace(/\<\/ul\>(\<br\>)+/g, '</ul>');
newString = newString.replace(/\<\/h([123456])\>(\<br\>)+/g, '</h$1>');
//This was keeping the previous clipboard item in the plaintext of the clipboard
//No longer using this as kind of confusing
//const plainText = await navigator.clipboard.readText();
const plainText = newString;
const blobPlain = new Blob([plainText], { type: "text/plain" });
const blobHtml = new Blob([`${newString}`], { type: "text/html" });
let data = [new ClipboardItem({
[blobPlain.type]: blobPlain,
[blobHtml.type]: blobHtml,
})];
await navigator.clipboard.write(data);
new Notice("Copied the cleaned and formatted text to your Clipboard for pasting into Outlook / Word!", 15000);
new Notice("Make sure you do a regular 'Full' paste and NOT paste as plain text!", 15000);
} else {
new Notice("Doing NOTHING because no text was selected!", 15000);
}
//By doing a return then it will not try to replace the selected text / apply the tR variable
return;
%>
@GitMurf
Copy link
Author

GitMurf commented Feb 11, 2022

NOTE: You have to do a regular paste and NOT a paste as plain text. I did that on purpose so if you had something on clipboard important before, it wouldn’t override it. So I keep the old clipboard in the plaintext paste and the cleaned copied note in the html part of the clipboard. Whenever you paste it needs to be into like outlook, word etc and doing a regular ctrl/cmd + V full paste and NOT plain text right click paste as plain text or ctrl + shift + v.

In Obsidian:

image

Pasted into Outlook:

image

@dcoales
Copy link

dcoales commented Feb 11, 2022

This is fantastic, thank you so much.

Is it possible to have a version that removes the #'s from headers but wraps the header in <h1> </h1> or <h2> </h2> markers as appropriate. When I type this in my note and copy it using your script the headers appear nicely in outlook. Weirdly, if I use ordinary ctrl-c instead of your script then it puts the html in as plain text instead of using the html.

@GitMurf
Copy link
Author

GitMurf commented Feb 12, 2022

Ok updated to add the following:

  • Headers
  • Bold markdown
  • Italics markdown
  • Highlight markdown
  • Inline code markdown
  • Strikethrough text markdown
  • Code blocks

cc @dcoales

BEFORE

image

AFTER

image

@GitMurf
Copy link
Author

GitMurf commented Feb 12, 2022

@dcoales when you have a chance please test and see if it is handling headers like you had hoped? Thanks!

@dcoales
Copy link

dcoales commented Feb 12, 2022

That's much better thank you.

I'm creating italics using foo but this is coming through unchanged i.e. not in italics. Am I doing it wrong.

I also added Google which came through as www.google.co.uk but wasn't clickable. Is there any chance of making this a clickable link. Sorry to be a pain :-)

Out of interest I checked out the plugin CopyToHtml which does create a clickable link using the the alias - but doesn't generate highlighted text properly so your script has the edge :-)

@GitMurf
Copy link
Author

GitMurf commented Feb 13, 2022

@dcoales can you please show a screenshot of both? The link thing I am literally just pasting the url so am not creating a link at all. It’s just the text. Whatever you paste it into should handle allowing it to be clickable. I’m not doing anything special.

@dcoales
Copy link

dcoales commented Feb 13, 2022

Here is the source text

## Heading 

### Sub Heading

This is some text with _Italilcs using underscore_ plus ==Highlighight== plus *italics using asterisks* plus __bold using underscore__ plus **bold using asterisks** 

This is a link to [Google](www.google.co.uk)

- And here are some bullets
	- And a nested bullet followed by a line separator

---

This renders as shown in the attached screenshot. It looks as though using underscores for bold and italic is the problem. If I use asterisks then it works fine.

With regards to the link - maybe an option to leaving it with the alias format rather than stripping out the part in the round brackets would work ?

image

In obsidian it appears as

image

@GitMurf
Copy link
Author

GitMurf commented Feb 13, 2022

@dcoales please test it now. The following should be implemented:

  • bold using underscores
  • italics using underscores
  • [markdown links](URL) now using HTML style a href element so link should be clickable and with alias still in MS products

Please confirm everything is now working as you hope?

@apoc527
Copy link

apoc527 commented Feb 13, 2022

This is amazing! A couple suggestions:

  • Change double-colons (for in-line DV metadata) to single colons
  • If there are headings in a list, try to apply same styling, else, simply delete the #s

This is SOOOO good.

EDIT:

I just added this and it works:

//Remove double colons
        lnOutput = lnOutput.replace(/::/g, ':')

The second bullet suggestion is beyond my skills.

@apoc527
Copy link

apoc527 commented Feb 13, 2022

A few more suggestions after using it to draft a client email:

  1. Ordered lists!
  2. Support for block quotes

@dcoales
Copy link

dcoales commented Feb 13, 2022

@GitMurf That's perfect for me. Thank you so much for doing this I really appreciate it.

@GitMurf
Copy link
Author

GitMurf commented Feb 14, 2022

@apoc527 i tried block quotes but Word and Outlook weren’t interpreting the html for it so I didn’t add it.

For the ordered lists do you just mean handle numbered lists?

@apoc527
Copy link

apoc527 commented Feb 14, 2022

Yea numbered lists is what I meant. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment