Skip to content

Commit

Permalink
Fallback to fuzzy search (#327)
Browse files Browse the repository at this point in the history
* Add github search resolver

* Use github search resolver as fallback for less

* Use github search resolver as fallback for sass

* Use github search resolver as fallback for haskell
  • Loading branch information
stefanbuck authored Mar 25, 2017
1 parent 588ae13 commit 7c785a5
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 4 deletions.
6 changes: 6 additions & 0 deletions lib/click-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ function getResolverUrls(dataAttr) {
return null;
}

if (typeof url === 'function') {
return {
func: url,
};
}

if (typeof url === 'object') {
return {
url: url.url.replace('{BASE_URL}', BASE_URL),
Expand Down
2 changes: 2 additions & 0 deletions lib/plugins/haskell.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HASKELL_IMPORT } from '../../packages/helper-grammar-regex-collection/index.js';
import insertLink from '../insert-link';
import preset from '../pattern-preset';
import githubSearch from '../resolver/github-search.js';

export default class Haskell {
static resolve({ path, target }) {
Expand All @@ -10,6 +11,7 @@ export default class Haskell {
`{BASE_URL}/${user}/${repo}/blob/master/src/${filePath}.hs`,
`{BASE_URL}/${user}/${repo}/blob/master/lib/${filePath}.hs`,
`{BASE_URL}/${user}/${repo}/blob/master/${filePath}.hs`,
githubSearch({ path, target: `${filePath}.hs` }),
`https://hackage.haskell.org/package/base/docs/${target.replace(/\./g, '-')}.html`,
];
}
Expand Down
2 changes: 2 additions & 0 deletions lib/plugins/less.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { LESS_IMPORT } from '../../packages/helper-grammar-regex-collection/inde
import insertLink from '../insert-link';
import preset from '../pattern-preset';
import relativeFile from '../resolver/relative-file.js';
import githubSearch from '../resolver/github-search.js';

export default class Less {

static resolve({ path, target }) {
return [
relativeFile({ path, target }),
githubSearch({ path, target }),
];
}

Expand Down
3 changes: 3 additions & 0 deletions lib/plugins/sass.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CSS_IMPORT } from '../../packages/helper-grammar-regex-collection/index
import insertLink from '../insert-link';
import preset from '../pattern-preset';
import relativeFile from '../resolver/relative-file.js';
import githubSearch from '../resolver/github-search.js';

export default class Sass {

Expand All @@ -14,6 +15,8 @@ export default class Sass {
return [
relativeFile({ path, target: `${prefixedTarget}.scss` }),
relativeFile({ path, target: `${prefixedTarget}.sass` }),
githubSearch({ path, target: `${prefixedTarget}.scss` }),
githubSearch({ path, target: `${prefixedTarget}.sass` }),
];
}

Expand Down
20 changes: 20 additions & 0 deletions lib/resolver/github-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { extname } from 'path';

export default function ({ path, target }) {
const [, user, repo] = path.split('/');
const extension = extname(target);

let params = `q=${target}+in:path+filename:${target}+repo:${user}/${repo}`;
if (extension) {
params += `+extension:${extension}`;
}

const url = `https://api.github.com/search/code?${params}`;

return async function githubSearch() {
const response = await fetch(url);
const json = await response.json();

return json.items[0].html_url;
};
}
8 changes: 7 additions & 1 deletion lib/utils/fetch.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import $ from 'jquery';

export default async (urls) => {
for (const { url, method = 'HEAD' } of urls) {
for (const { url, func, method = 'HEAD' } of urls) {
try {
if (func) {
return {
url: await func(), // eslint-disable-line no-await-in-loop
};
}

// Normally, you wouldn't use `await` inside of a loop.
// However, we explicity want to do this sequentially.
// See http://eslint.org/docs/rules/no-await-in-loop
Expand Down
5 changes: 4 additions & 1 deletion test/plugins/haskell.test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import assert from 'assert';
import Haskell from '../../lib/plugins/haskell';
import githubSearch from '../../lib/resolver/github-search.js';

describe('haskell', () => {
const path = '/user/repo/blob/d6/lib/plugins/javascript.js';
const target = 'Foo.Bar';

it('resolves links', () => {
assert.deepEqual(
Haskell.resolve({ path, target: 'Foo.Bar' }),
Haskell.resolve({ path, target }),
[
'{BASE_URL}/user/repo/blob/master/src/Foo/Bar.hs',
'{BASE_URL}/user/repo/blob/master/lib/Foo/Bar.hs',
'{BASE_URL}/user/repo/blob/master/Foo/Bar.hs',
githubSearch({ path, target }).toString(),
'https://hackage.haskell.org/package/base/docs/Foo-Bar.html',
],
);
Expand Down
5 changes: 4 additions & 1 deletion test/plugins/less.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import assert from 'assert';
import Less from '../../lib/plugins/less';
import githubSearch from '../../lib/resolver/github-search.js';

describe('Less', () => {
const path = '/octo/dog.less';
const target = 'foo.less';

it('resolves links', () => {
assert.deepEqual(
Less.resolve({ path, target: 'foo.less' }),
Less.resolve({ path, target }),
[
'{BASE_URL}/octo/foo.less',
githubSearch({ path, target }).toString(),
],
);
});
Expand Down
8 changes: 7 additions & 1 deletion test/plugins/sass.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import assert from 'assert';
import Sass from '../../lib/plugins/sass';
import githubSearch from '../../lib/resolver/github-search.js';

describe('Sass', () => {
const path = '/octo/dog.scss';
const target = 'foo';

it('resolves link when target does not have a file extension', () => {
assert.deepEqual(
Sass.resolve({ path, target: 'foo' }),
Sass.resolve({ path, target }),
[
'{BASE_URL}/octo/_foo.scss',
'{BASE_URL}/octo/_foo.sass',
githubSearch({ path, target }).toString(),
githubSearch({ path, target }).toString(),
],
);
});
Expand All @@ -20,6 +24,8 @@ describe('Sass', () => {
[
'{BASE_URL}/octo/_foo.scss',
'{BASE_URL}/octo/_foo.sass',
githubSearch({ path, target }).toString(),
githubSearch({ path, target }).toString(),
],
);
});
Expand Down
45 changes: 45 additions & 0 deletions test/resolver/github-search.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import assert from 'assert';
import sinon from 'sinon';
import githubSearch from '../../lib/resolver/github-search.js';

describe('github-search', () => {
const sandbox = sinon.sandbox.create();
const fetchStub = sinon.stub(window, 'fetch');

const path = '/octo/foo.txt';
const target = 'bar.txt';

afterEach(() => {
fetchStub.reset();
sandbox.reset();
});

after(() => {
sandbox.restore();
});

it('returns a function', () => {
assert.deepEqual(
typeof githubSearch({ path, target }),
'function',
);
});

it('calls the github search api', () => {
githubSearch({ path, target })();

assert.deepEqual(
fetchStub.args[0][0],
'https://api.github.com/search/code?q=bar.txt+in:path+filename:bar.txt+repo:octo/foo.txt+extension:.txt',
);
});

it('does not append query param "extension" when target does not have a file extension', () => {
githubSearch({ path, target: 'bar' })();

assert.deepEqual(
fetchStub.args[0][0],
'https://api.github.com/search/code?q=bar+in:path+filename:bar+repo:octo/foo.txt',
);
});
});

0 comments on commit 7c785a5

Please sign in to comment.