const url = require('url') const {shell} = require('electron') const _ = require('underscore-plus') const LINK_SCOPE_REGEX = /markup\.underline\.link/ module.exports = { activate () { this.commandDisposable = atom.commands.add('atom-text-editor', 'link:open', () => this.openLink()) }, deactivate () { this.commandDisposable.dispose() }, openLink () { const editor = atom.workspace.getActiveTextEditor() if (editor == null) return let link = this.linkUnderCursor(editor) if (link == null) return if (editor.getGrammar().scopeName === 'source.gfm') { link = this.linkForName(editor, link) } const {protocol} = url.parse(link) if (protocol === 'http:' || protocol === 'https:' || protocol === 'atom:') shell.openExternal(link) }, // Get the link under the cursor in the editor // // Returns a {String} link or undefined if no link found. linkUnderCursor (editor) { const cursorPosition = editor.getCursorBufferPosition() const link = this.linkAtPosition(editor, cursorPosition) if (link != null) return link // Look for a link to the left of the cursor if (cursorPosition.column > 0) { return this.linkAtPosition(editor, cursorPosition.translate([0, -1])) } }, // Get the link at the buffer position in the editor. // // Returns a {String} link or undefined if no link found. linkAtPosition (editor, bufferPosition) { const token = editor.tokenForBufferPosition(bufferPosition) if (token && token.value && token.scopes.some(scope => LINK_SCOPE_REGEX.test(scope))) { return token.value } }, // Get the link for the given name. // // This is for Markdown links of the style: // // ``` // [label][name] // // [name]: https://github.com // ``` // // Returns a {String} link linkForName (editor, linkName) { let link = linkName const regex = new RegExp(`^\\s*\\[${_.escapeRegExp(linkName)}\\]\\s*:\\s*(.+)$`, 'g') editor.backwardsScanInBufferRange(regex, [[0, 0], [Infinity, Infinity]], ({match, stop}) => { link = match[1] stop() }) return link } }