Skip to content
This repository has been archived by the owner on Sep 27, 2018. It is now read-only.

Decaffeinate #25

Merged
merged 4 commits into from
Nov 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .coffeelintignore

This file was deleted.

37 changes: 0 additions & 37 deletions coffeelint.json

This file was deleted.

65 changes: 0 additions & 65 deletions lib/link.coffee

This file was deleted.

74 changes: 74 additions & 0 deletions lib/link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const url = require('url')
const {shell} = require('electron')
const _ = require('underscore-plus')

let selector = null

module.exports = {
activate () {
atom.commands.add('atom-workspace', 'link:open', () => this.openLink())
},

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.getBuffer(), link)
}

const {protocol} = url.parse(link)
if (protocol === 'http:' || protocol === 'https:') 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) {
if (selector == null) {
const {ScopeSelector} = require('first-mate')
selector = new ScopeSelector('markup.underline.link')
}

const token = editor.tokenForBufferPosition(bufferPosition)
if (token && token.value && selector.matches(token.scopes)) 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 (buffer, linkName) {
let link = linkName
const regex = new RegExp(`^\\s*\\[${_.escapeRegExp(linkName)}\\]\\s*:\\s*(.+)$`, 'g')
buffer.backwardsScanInRange(regex, buffer.getRange(), ({match, stop}) => {
link = match[1]
stop()
})
return link
}
}
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@
"underscore-plus": "1.x"
},
"devDependencies": {
"coffeelint": "^1.9.7"
"standard": "^10.0.3"
},
"standard": {
"env": {
"atomtest": true,
"browser": true,
"jasmine": true,
"node": true
},
"globals": [
"atom"
]
}
}
103 changes: 103 additions & 0 deletions spec/async-spec-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/** @babel */

export function beforeEach (fn) {
global.beforeEach(function () {
const result = fn()
if (result instanceof Promise) {
waitsForPromise(() => result)
}
})
}

export function afterEach (fn) {
global.afterEach(function () {
const result = fn()
if (result instanceof Promise) {
waitsForPromise(() => result)
}
})
}

['it', 'fit', 'ffit', 'fffit'].forEach(function (name) {
module.exports[name] = function (description, fn) {
if (fn === undefined) {
global[name](description)
return
}

global[name](description, function () {
const result = fn()
if (result instanceof Promise) {
waitsForPromise(() => result)
}
})
}
})

export async function conditionPromise (condition, description = 'anonymous condition') {
const startTime = Date.now()

while (true) {
await timeoutPromise(100)

if (await condition()) {
return
}

if (Date.now() - startTime > 5000) {
throw new Error('Timed out waiting on ' + description)
}
}
}

export function timeoutPromise (timeout) {
return new Promise(function (resolve) {
global.setTimeout(resolve, timeout)
})
}

function waitsForPromise (fn) {
const promise = fn()
global.waitsFor('spec promise to resolve', function (done) {
promise.then(done, function (error) {
jasmine.getEnv().currentSpec.fail(error)
done()
})
})
}

export function emitterEventPromise (emitter, event, timeout = 15000) {
return new Promise((resolve, reject) => {
const timeoutHandle = setTimeout(() => {
reject(new Error(`Timed out waiting for '${event}' event`))
}, timeout)
emitter.once(event, () => {
clearTimeout(timeoutHandle)
resolve()
})
})
}

export function promisify (original) {
return function (...args) {
return new Promise((resolve, reject) => {
args.push((err, ...results) => {
if (err) {
reject(err)
} else {
resolve(...results)
}
})

return original(...args)
})
}
}

export function promisifySome (obj, fnNames) {
const result = {}
for (const fnName of fnNames) {
result[fnName] = promisify(obj[fnName])
}
return result
}
Loading