Script: Replace link references with real links in Markdwon

The following script replaces all link references in an MD document with the real links.
It arose from the discussion in this thread: Changing the image size of linked images in markdown document created by DevonThink extension

For example,

sometext [Link text][1]
…
[1]: https://www.example.com

will be changed to

sometext [Link text](https://www.example.com)
…
[1]: https://www.example.com

As you can see, the link references at the end of the document are preserved and the URLs themselves are hoisted into the appropriate place in the document. The reference links at the end shouldn’t do any harm and are easy to remove manually.

As it stands, the script works on the currently selected records in DT and can be run from Script Editor (having set the language selector to “JavaScript”) or as a stand-alone script from the script menu. The latter is described in detail in the fine DT manual.

It can also be used in a smart rule with the following changes:

  • replace (()=> { with function performsmartrule(records) {
  • remove the line const records = …
  • change })() to }

Afterward, the code can run as internal or external script in a smart rule.

I’ve done minimal testing of the script with only a single MD file. Also, the code assumes that each reference link appears only once in the document. That shouldn’t be too much of a limitation. If you stumble upon an MD document with duplicated reference links, use replaceAll instead of replace and add the g flag to the regular expression.

(() => {
  const app = Application("DEVONthink 3")
  app.includeStandardAdditions = true;
  const records = app.selectedRecords();
  records.forEach(r => {
    const links = getReferenceLinks(r.plainText())
    r.plainText = replaceLinks(r.plainText(), links);
  })
})()

function getReferenceLinks(txt) {
  const allLinks = [...txt.matchAll(/^\[(\d+)\]:\s+(.*)$/gm)];
  const linkArray = {};
  allLinks.forEach(l => {
    const index = l[1];
    const URL = l[2];
    linkArray[index] = URL;
  })
  return linkArray;
}

function replaceLinks(txt, links) {
  console.log(links);
  Object.keys(links).forEach(k => {
    const URL = links[k];
    const regEx = new RegExp(`]\\[${k}\\]`);
    txt = txt.replace(regEx, `](${URL})`);
  })
  return txt;
}