I have a changelog file formatted using Github's markdown.
Initially I used inline links for every link I needed to add, that is:
This is some [example](http://www.stackoverflow.com) line of text.
Over time, as the file grew in size, it became a bit messy due mainly to this way of inserting links.
I'd like to convert all links from inline to reference (see description of each), that is convert the above line to this:
This is some [example][1] line of text.
[1]: http://www.stackoverflow.com
Since the file is rather large and contains many inline links, I was wondering if there is some automated way to do this. I use Sublime Text 3 to edit, but I couldn't find a suitable package for this task. Perhaps some clever regex?
Came across this question thanks to Google. Maybe this can help others:
My answer isn't Sublime specific, but if you're using JavaScript (Node) already, I'd use a Markdown parser and CST transformer like remark.
For example, to transform all the inline links in README.md
to numerically-ascending reference-style links, you could run the following at your project's root:
npm install --save-dev remark-cli remark-renumber-references
npx remark --no-stdout --output --use renumber-references README.md
Or, if you want reference-style links derived from the source uri:
npm install --save-dev remark-cli remark-defsplit
npx remark --no-stdout --output --use defsplit README.md
Hopefully this info helps people like me not waste a whole day hacking together some horrendously unreliable regexp-based solution to this :)
That's a great requirement!
I've just created a new Node.js program (I know it's not a GUI but seems something more people would like the capability of) to do this on GitHub.
Here's also the code:
// node main.js test.md result.md
var fs = require('fs')
fs.readFile(process.argv[2], 'utf8', function (err, markdown) {
if (err) {
return console.log(err);
}
var counter = 1;
var matches = {};
var matcher = /\[.*?\]\((.*?)\)/g;
while (match = matcher.exec(markdown)) {
if (!matches[match[1]]) matches[match[1]] = counter++;
}
console.log(matches);
Object.keys(matches).forEach(function(url) {
var r = new RegExp("(\\[.*?\\])\\(" + url + "\\)", "g");
markdown = markdown.replace(r, "$1[" + matches[url] + "]");
markdown += "\n[" + matches[url] + "]: " + url;
});
fs.writeFile(process.argv[3], markdown, 'utf8', function (err) {
if (err) return console.log(err);
});
});
Save this as mdrelink.py
in your Packages folder, and you can then run it with
view.run_command('mdrelink');
from within the command console.
I think I got the order thingy right – reversing is necessary because otherwise it would mess up the already cached indexes of next items. It should also automatically skip already used link numbers. My first Python and my first Sublime plugin, so please be gentle with me.
import sublime, sublime_plugin
class mdrelinkCommand(sublime_plugin.TextCommand):
def run(self, edit):
oldlinks = []
self.view.find_all("^\s*(\[\d+\]):", sublime.IGNORECASE, "\\1", oldlinks)
newlinkpos = self.view.find_all("\[.+?\](\(.+?\))")
orgtext = []
self.view.find_all("(\[.+?\])\(.+?\)", sublime.IGNORECASE, "\\1", orgtext)
orglink = []
self.view.find_all("\[.+?\]\((.+?)\)", sublime.IGNORECASE, "\\1", orglink)
orglink.reverse()
self.view.insert(edit, self.view.size(), '\n\n')
counter = 1
newnumbers = []
for r in newlinkpos:
while '['+str(counter)+']' in oldlinks:
counter += 1
oldlinks.append('['+str(counter)+']')
line = '[' + str(counter)+']: '+ orglink.pop() + '\n'
newnumbers.append(' ['+str(counter)+']')
self.view.insert(edit, self.view.size(), line)
for r in reversed(newlinkpos):
self.view.replace(edit, r, orgtext.pop()+newnumbers.pop())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With