Converting Evernote Wiki Links to Bear Wiki Links

Long story short, I’m moving from Evernote to Bear, but noticed that when I import notes all my Evernote wiki style links between notes just hyperlink back to Evernote once they’ve been imported to Bear.

After a long search I found THIS python code on github. Although I am an absolute beginner when it comes to coding, I was able to utilize some friends expertise and some Bing AI help to modify and simplify the code so that it converts all evernote wiki links to bear wiki links, as well as converting all colored text to color formatted text in an evernote note to markdown highlighted text in bear.

This is all done with a few pretty simple RegEx Substitution commands…

# the re.sub expression below converts evernote wiki links to Bear note wiki links by replacing all evernote:/// links with the actual name of the evernote note wrapped in [[ ]]
     content = re.sub(r'(<a[^>]*?href="evernote[^>]*?>)(.*?)(</a>?)', r"[[\2]]", content)

# the re.sub expression below escapes all "/" found between [[ ]] by replaceing them with "\/" (which is necessary because otherwise Bear creates a new note when the wiki is clicked)
     content = re.sub(r'\[\[[^\]]*\/[^\]]*\]\]', lambda x: x.group().replace('/', '\\/'), content) 

# the re.sub expression below turns ALL colored text into highlighted text in bear by wrapping the text in == * ==
     content = re.sub(r'(<span style="color:rgb[^>]*?>\s*)(.*?)(\s*</span>?)', r"==\2==", content)

I’m sure I’m not the only one with who wants their Evernote wiki links to function as Bear note wiki links and my hope was that this might be something you could include in the bear app importer.

As mentioned in my original post I’m a newb when it comes to coding and am still figuring out how to use git hub, but I’ve included the whole python code below for anyone who want to try it for themselves.

#!/usr/bin/env python3
"""e2b: a simple python script that converts Evernote note links and colored text to Bear note links and highlighted markdown text"""
import os
import re

def input_enex_path():
    """Read .enex files in directory.
    ---
    - Accept path to directory from user input
    - Verify that directory is valid with os.path.exists()
    - Scan directory with os.scandir and create files object
    - Create directory for converted files
    - Run function to convert Evernote note links and colored text to Bear note links and highlighted text in each file
    """
    path = input("Please input the path to a directory with Evernote exports: ")
    if not os.path.exists(path):
        print(f"Not a valid file path:\n{path}")
        return
    else:
        print(f"Valid file path: {path}")
    if not os.path.exists(f"{path}/bear"):
        os.mkdir(f"{path}/bear")
    for file in os.scandir(path):
        if file.is_file() and file.name.endswith(".enex"):
            convert_links(file)

def convert_links(file):
    """convert Evernote note links and colored text to Bear note links and highlighted markdown text.
    ---
    - Replace Evernote note link URIs, but not other URIs, with Bear note links
    - Replace colored text from Evernote with Highlighted text in Bear Note
    - Write to a new file in the bear subdirectory
    """
    try:
        print(f"Converting {file.name}...")
        with open(file) as enex:
            content = enex.read()
            # the re.sub expression below converts evernote wiki links to Bear note wiki links by replacing all evernote:/// links with the actual name of the evernote note wrapped in [[ ]]
            content = re.sub(r'(<a[^>]*?href="evernote[^>]*?>)(.*?)(</a>?)', r"[[\2]]", content)
            # the re.sub expression below escapes all "/" found between [[ ]] by replaceing them with "\/" (which is neccessary because otherwise Bear creates a new note when the wiki is clicked)
            content = re.sub(r'\[\[[^\]]*\/[^\]]*\]\]', lambda x: x.group().replace('/', '\\/'), content) 
            # the re.sub expression below turns ALL colored text into highlighted text in bear by wrapping the text in == * ==
            content = re.sub(r'(<span style="color:rgb[^>]*?>\s*)(.*?)(\s*</span>?)', r"==\2==", content)
            with open(f"{os.path.dirname(file)}/bear/{file.name}", "x") as new_enex:
                new_enex.write(content)
            print("Done. New file available in the bear subdirectory.")
    except Exception as e:
        print(f"An error occurred:\n{e}\nPlease try again.")

if __name__ == "__main__":
    input_enex_path()

HERE is a link the code on github

Hello and thank you very much for sharing this.

I might be wrong but by reading the script I think it assumes the note link title is not edited by the user but if this is the case the wiki link might point to a missing note (maybe note link renaming is no longer possible in EN?). The way to go should be using the hard link (evernote://) but IIRC the Enex file doesn’t carry the same code used by the link.

I have to verify the above but if everything checks out I don’t see why not integrating this in the Enex importer.

You’re assumption is correct that if the note has been renamed or the note link title has been edited by the user that it will point to a missing note. And unfortunately there isn’t really anything that can be done about that, other than going through every note in Evernote by hand and resetting the links manually. I’ve even reached out to Evernote about a library wide resetting of wiki links to their current name, but it’s not something that is currently possible or on their priority list.

Sadly for me this will be the case for a good number of own notes/links, but it’s way better than not having any of them transfer over.

Thanks for considering this though, and I totally understand if the lack of consistency makes this feature not a great candidate for universal adoption.

Also just to clarify that second re.sub function in my original code just escaped all the “/” characters within a wiki link [] since without doing that it messes with the title and ends up making the link point to a missing note. I went through and tested every special character and I’m pretty sure that the “/” was the only one that required escaping to maintain the wiki link functionality.

Yes / needs to be converted to \/ because we use this character for header linking.

I altered my python script so that in addition to wrapping the note name found in the enex file in [[ ]] the regex substitution below also adds a hyperlink to the original evernote note labeled simply as {ev} so that if the original note name has been changed you can still reliably access the original note in evernote.

content = re.sub(r'(<a[^>]*?href="(evernote[^"]*?)"[^>]*?>)(.*?)(</a>?)', r"[[\3]] [{ev}](\2)", content)

essentially turning strings like this found in the exported enex files…

<div><a style="--en-preferPlainlink:true;" href="evernote:///view/7319568/s60/58909644-ddbc-b939-6198-176ef4827b6e/" rev="en_rl_none">NOTE NAME</a></div>

into strings like this…

<div>[[NOTE NAME]] [{ev}](evernote:///view/7319568/s60/58909644-ddbc-b939-6198-176ef4827b6e/)</div>

appearing in bear like this with markdown visible…
Screenshot 2023-11-30 at 2.15.09 PM
and like this with markdown hidden…
Screenshot 2023-11-30 at 2.15.54 PM

hopefully this helps the devs or anyone else looking to import their notes from Evernote and retain as much wiki link functionality as possible