How to convert all my links to markdown links when I paste?

I find it easier to know what kind of links I have if for example all the external links are markdown links where it shows the gray link icon on the right side of the link, like the links below:
image

Now those were converted manually.
Link 1, is also external, but it’s not converted. Link 2 is internal, which I want to keep without the icon.

Is there a way to make this a default where external links are automatically formatted as markdown so they can have the icon automatically, instead of me doing it manually?

1 Like

The icon will show only for external links.
I write mostly longform with a view to publishing the material so I always use [description](https://somewebsite.com/bla-bla/bla-bla-bla.html) format. Does the icon pop up if you do it in such a way?

1 Like

Only if I select the link, hit CMD K (on a Mac) and then manually add the link inside the parenthesis.
I would like it to always do that so then all external links would have the icon, whereas the internal links wouldn’t have it

Kapture 2023-11-17 at 21.46.11

There is no setting in Obsidian. But you can set up a Templater script that does a conversion.

<%*
// Add description for external link

clipboard = (await tp.system.clipboard());
// Regex replace content
clipboard = clipboard.replace(/(.*)/, "[$1]($1)");

tR += clipboard;

_%>
  • Didn’t try but should work. Using this only makes sense with external links URLs, of course.

Add this Templater script to your Templater folder and in Templater settings add a key binding to it.
Usage: copy URL from net, place your cursor in Obsidian note and press key combo. The URL with the same URL in description will be pasted in the editor.

1 Like

Thank you so much for that!
I’m pretty new to Obsidian, so the whole Templater thing (and plugins in general) are very foreign to me, but I guess I was able to make it work. Let me share what I have to see if you can confirm this is the right way to add templates and all that:

So I installed the Templater plugin, then created the folder “_Templates” on the root of my vault and added a new note “Automatic Markdown Links”:
image

Inside, I added your script:
image

In the Templater settings, I selected the folder:

Then added the file to the Hotkeys section:

I set the hotkey:

So now when I use ⌘+V, it pastes the text or link the way it used to. When I use ⌥+V, it pastes the link using the markdown version

It’s working. I just want to make sure that the whole process is correct?

Also, if it isn’t too much to ask (if it is, no worries, I already appreciate your time and help):
Is it possible for the script to check what the clipboard contains such as https, https, or www. (including the dot at the end, to make it more specific)?
I would like to use the same shortcut for both scenarios, so I don’t have to use 2, and the script would paste it the “old way” if https, http, or www. isn’t present, and if it is present, it uses the way you scripted.

Again, if this is too complex, it’s totally fine. I can probably create a Keyboard Maestro macro to achieve the same thing, but if the script could do that automatically, it would be a cleaner solution.

Thanks again for your time and help! :raised_hands:

1 Like

If you are new to Templater, you did really well.
I was going to include the http in the regex but decided not to because I thought you will use a specific key combination anyway. Because – silly me – I thought there was going to be a conflict, but actually, there is no CMD + C and CMD + V built-in bindings as Obsidian uses the OS key combination.

Good on you to insist because it is much more elegant this way:

<%*
// Add description for all non-internal links in clipboard

clipboard = (await tp.system.clipboard());
// Regex replace content
clipboard = clipboard.replace(/((https?|obsidian|ftp|file):\/\/\S+)/gm, "[$1]($1)");

tR += clipboard;
_%>

So add normal CMD + V for this and it will paste every link the way you want.

NB: If you don’t use this in an active note (for example, in Surfing plugin), Templater will throw an error, but you can ignore that or use SHIFT + CMD + V.

Yes, I’m new to pretty much everything when it comes to Obsidian. I’ve been using it for basic things, like a normal notes app, but other than that, it’s all new to me. Glad to know I got that Templater process right :slight_smile:

So I was testing it and I can indeed use the same shortcut CMD+V and it knows what normal text is and when to convert to a link with description when using https or http:
image

Can I include everything that contains www. as well to add the description, like this:
www.dwyatt.com

I noticed that it only adds the icon if the link inside the parenthesis included either http or https for example:

[www.dwyatt.me](http://www.dwyatt.me)
[www.dwyatt.me](https://www.dwyatt.me)

So I guess the script would have to check if the clipboard contains www. and if so, replace it with http://www. (since not all websites use https, it’s safer to use http to make sure it will always work).

Is this possible and relatively easy to implement?
Again, if not, it’s totally fine. It’s already great that the other links, with will be what I will be pasting 99.9% of the time.

Thanks!

As a newbie, I still don’t know what that means, but thank you for the tip.
I’m sure if I get to that point where I need non-active notes (whatever that is), my brain will probably remember this. Thanks for the “warning” :wink:

We can add support for www. without the http or https protocol (currently it supports these and a few others I had in mind), but Obsidian won’t add the icon you wanted, so there’s no point.

Templater scripts need an active note to work, which means the cursor is inside an open note. It won’t work when you are in the quickswitcher menu or when browsing the net with the Surfing plugin (I use that for net when I do Obsidian work on PC).

Sorry, I’m not sure I understand this part…

For example in Keyboard Maestro (if you’re familiar with it), I can create a macro that emulates this. Let’s say I was using a specific shortcut in Obsidian just for those links, the way we set it up in the beginning, like CMD+L, while CMD+V was being used for normal text.

Now with KM I can create a macro that get’s triggered when I hit CMD+V and it checks the clipboard content. If it contains https, http OR www. it runs action A, which includes an action to simulate the CMD+L keystroke (for the links). If the clipboard doesn’t include https, http OR www. then it “hits” CMD+V

So I was wondering if something similar to this would be possible, or something the way I just described where the script would analyze what’s about to be pasted and if there’s www. in it, when it pastes it, it converts it to http://www. so when I paste www.google.com instead of it pasting www.google.com, it would automatically create [http://www.google.com](http://www.google.com)

Not sure if it’s making any sense?

Try this then:

<%*
// Add description for all non-internal links in clipboard

let clipboard = await tp.system.clipboard();

// Regex replace content
clipboard = clipboard.replace(
  /(?<!https?:\/\/)(?<!\S)(www\.\S+)|(ftp|obsidian|file):\/\/\S+|(https?:\/\/\S+)/gm,
  function(match, p1, p2, p3) {
    if (p1) {
      return `[${p1}](http://${p1})`;
    } else if (p2) {
      return `[${match}](${match})`;
    } else {
      return `[${p3}](${p3})`;
    }
  }
);

tR += clipboard;
_%>

Still pastes it as a normal link

image

I wish I could understand the script and contribute with some suggestions, but it’s not something I’m comfortable with.
I have the idea for how the workflow could be, like the one I explained with KM, but when it comes to scripts, not my field of expertise.

I’ve been learning a bit of RegEx here and there, but very basic stuff

The www.dwyatt.com should have worked.

Try this:

<%*
// Add description for all non-internal links in clipboard

let clipboard = await tp.system.clipboard();

// Regex replace content
clipboard = clipboard.replace(
  /(?<!https?:\/\/)((www\.\S+)|(ftp|obsidian|file):\/\/\S+|(https?:\/\/\S+)|(?:\b\S+\.(?:com|net|org|io|co|uk|edu|gov|info|biz|tv|me|online)\b))/gm,
  function(match, p1, p2, p3, p4, p5) {
    if (p1) {
      return `[${p1}](http://${p1})`;
    } else if (p2) {
      return `[${p2}](${p2})`;
    } else if (p3) {
      return `[${p3}](${p3})`;
    } else if (p4) {
      return `[${p4}](${p4})`;
    } else {
      return `[${p5}](${p5})`;
    }
  }
);

tR += clipboard;
_%>

When I tried your previous script, and now with this one, I always experienced some errors. Then they ended up going away when I disabled Templater, closed Obsidian, opened it again, enabled Templater.
Don’t know if this helps:

image

So with your first script, the shorter version, no issues. It just started happening with these 2 last versions

No error here.
Next time add any error messages in text format using backticks (1, 3, or 4).

This new one also works for me:

<%*
// Add description for all non-internal links in clipboard

let clipboard = await tp.system.clipboard();

// Regex replace content
clipboard = clipboard.replace(
  /(?<!https?:\/\/)(www\.\S+)|(ftp|obsidian|file):\/\/\S+|(https?:\/\/\S+)|(?:\b\S+\.(?:com|net|org|io|co|edu|gov|info|biz|tv|me|online|uk|us|ca|au|de|fr|it|es|nl|ru|cn|jp|br|mx|se|no|fi|dk|pl|gr|cz|ch|at|be|hu|sk)\b)/gm,
  function(match, p1, p2, p3, p4) {
    if (p1) {
      return `[https://${p1}](https://${p1})`;
    } else if (p2) {
      return `[${p2}](${p2})`;
    } else if (p3) {
      return `[${p3}](${p3})`;
    } else {
      return `[${p4}](${p4})`;
    }
  }
);

tR += clipboard;
_%>

An alteration:

<%*
// Add description for all non-internal links in clipboard

let clipboard = await tp.system.clipboard();

// Regex replace content
clipboard = clipboard.replace(
  /(?<!https?:\/\/)(www\.\S+)|(ftp|obsidian|file):\/\/\S+|(https?:\/\/\S+)|(?:\b\S+\.(?:com|net|org|io|co|edu|gov|info|biz|tv|me|online|uk|us|ca|au|de|fr|it|es|nl|ru|cn|jp|br|mx|se|no|fi|dk|pl|gr|cz|ch|at|be|hu|sk)\b)/gm,
  function(match, p1, p2, p3, p4) {
    switch (true) {
      case !!p1:
        return `[https://${p1}](https://${p1})`;
      case !!p2:
        return `[${p2}](${p2})`;
      case !!p3:
        return `[${p3}](${p3})`;
      default:
        return `[${p4}](${p4})`;
    }
  }
);

tR += clipboard;
_%>

There’s some progress now…
The www version is now working, but now normal text was pasted as a 0 and a link at the same time

image

The second script shows an error

Templater Error: Template parsing error, aborting. 
 Template syntax error: Unexpected token ']'
log_error @ plugin:templater-obsidian:61

So the first version doesn’t show any error, but it’s converting normal text to link and also converting the text to 0, no matter what text I copied

The Linux and Mac environments should not differ and I’m afraid I cannot investigate as I cannot simulate a Mac environment here.

No null characters appear here on normal content, with or without any URLs in the clipboard.

1 Like

@gino_m
Here’s what I just noticed:
The 0 issue was that I copied this dwyatt.me

If I copied something else like 1234 , it pastes it as text

image

It seems that you have something on your code that’s targeting certain extensions. I tried with dwyatt.com and I got the same thing, the 0

Also, is it possible for the link with www to use http and not https, because not all websites use https and it’s more reliable to use http as the default?

No problem.
I think I will try your first script and then use KM to work around the www issue.
It’s probably easier since you can’t experience what I’m experiencing.

I truly appreciate your time and help on this.
Sorry that it’s not working as expected…

I am now able to reproduce.

This last script seems to work for all cases:

<%*
// Add description for all non-internal links in clipboard
let clipboard = await tp.system.clipboard();

// Regex replace content
clipboard = clipboard.replace(
  /(?<!https?:\/\/)(www\.\S+)|(ftp|obsidian|file):\/\/\S+|(https?:\/\/\S+)|(?:\b\S+\.(?:com|net|org|io|co|edu|gov|info|biz|tv|me|online|uk|us|ca|au|de|fr|it|es|nl|ru|cn|jp|br|mx|se|no|fi|dk|pl|gr|cz|ch|at|be|hu|sk)\b)/gm,
  function(match, p1, p2, p3, p4) {
    if (p1) {
      return `[https://${p1}](https://${p1})`;
    } else if (p2) {
      return `[${p2}](${p2})`;
    } else if (p3) {
      // Check if p3 already contains http or https, if not, add https
      return p3.startsWith('http') ? `[${p3}](${p3})` : `[${p3}](https://${p3})`;
    } else if (p4 && /^(?:https?|ftp|obsidian|file):\/\//.test(p4)) {
      return `[${p4}](${p4})`;
    } else {
      // If there's no match for known protocols, add https protocol
      return `[https://${match.trim()}](https://${match.trim()})`;
    }
  }
);

tR += clipboard;
_%>
1 Like