markdown links to Windows paths?

Testing whether I could use Observable to render a table of documents with links to their locations in a Windows directory, I receive:

TypeError: Cannot read property ‘replace’ of undefined
Please report this to

e.g. with this path


For HTML, it’s a similar issue:

TypeError: Cannot read property ‘trim’ of undefined

<a href="C:\User\aaron\1.doc">test</a>

When I try this locally with HTML, however, I have no problems.

Is this an observable limitation? Or something else?

You’ll need to convert the Windows backslashes to the forward slashes used in URIs, (and you probably want to use the file:// syntax as well):

<a href="file:///C:/User/aaron/1.doc">test</a>
1 Like

Thanks Bryan! Your answer is very helpful and appreciated, but it’s unfortunate that one must implement such a conversion :frowning:

As a bit of follow-up – to better understand issues and going beyond getting the links to work:

Why doesn’t the URL conversion occur “auto-magically” with an Observable cell, whereas it does for an HTML file sitting on my computer?

That is, with a standard HTML file on my computer, the browser takes the windows path, downloads the file, and shows me in the download tabs that it did so using the file:// syntax.

Also, if I supply the path with from a CSV file with JavaScript, the path looks to be working OK

<a href="${windows_docs[1].document_path}">test</a>

However, clicking the cell won’t draw down the file, although I can use the mouse to ‘copy path’, which will copy in the file:// syntax and, if pasted in my browser manually, downloads the file as expected.

so weird.

it’s unfortunate that one must implement such a conversion :frowning:

Here’s a trick that might help. If you type / paste the path to your local file into the address bar in a new browser tab and hit enter, your browser should automatically convert it into a new file:// url that you can copy and paste.

For the paths coming from CSV files, you could use a function to convert the URLs; here’s one adapted from a JSfiddle:

function filePathToUrl(path) {
    path = path.replace(/\\/g, '/');
    path = path.replace(/ /g, '%20');
    const drive = /(.)\:\//;
    return path.replace(drive, 'file:///$1:/');

(Not too well-tested, may break on some edge cases…)
You can use it like this:

<a href="${filePathToUrl(windows_docs[1].document_path)}">test</a>

why doesn’t this conversion occur “auto-magically” with an Observable cell, whereas it does for an HTML file sitting on my computer?

I wasn’t aware that you could do this with local HTML files – my guess would be that is because browsers are inclined to relax security restrictions in favor of convenience in that setting. There’s a little more discussion about security and local file paths in this SO answer. That may go part way to explaining “weird” behavior.

1 Like

Thank you for all the research and links. This is super informative!

From the the SO information you linked, and as verified with a bit of testing, it doesn’t seem possible to use the file:/// protocol on Observable and have it download files on one’s computer. When I do this (assuming because the browser is reading the URL path as as file://localhost/C:/User/aaron/1.doc) the page attempts to open a separate Observable window—and clearly that file won’t be found on Observable. This same thing happens when trying to download and host the notebook elsewhere, like GitHub or AWS—localhost will not refer to your local computer, but to the sever hosting the file. This windows computer I am using won’t allow me to run a local http server (like with python), so that may work, but it’s an extra step anyway so not well suited to my purpose (which is to describe a body of literature sitting on a shared Windows network drive).