js bookmarklet: prompt for (part of) gitlab project name, and then open url to that project.

by Laurens Maneschijn

HTML

js bookmarklet: prompt for (part of) gitlab project name, and then open url to that project.

using gitlab api with async await fetch() construction.

matching on simplified order-sensitive case-insensitive search, 
then ordering by smallest levenshstein distance.

<hr>
limitation: only works when using bookmark on same domain.
if called from another domain we only get the last 3 projects.
<hr>

<a href="javascript:(function(){ async function load_projects() { var items = [], response, data, per_page = 100, page = 1, next_page, url; while(true) { console.log(&apos;---&apos;); var url = &apos;https://orange.dev/api/v4/projects?per_page=&apos;+per_page+&apos;&amp;page=&apos;+page; console.log(url); response = await fetch(url); data = await response.json(); if(data &amp;&amp; Array.isArray(data)) { items = items.concat(data); } next_page = await response.headers.get(&apos;X-Next-Page&apos;); if(next_page &gt; page) { page = next_page; } else { break; } } return data; } async function get_projects() { var window_key = &apos;__tmp__gitlab_projects_orange_dev&apos;; if (!window[window_key]) { window[window_key] = await load_projects(); } return window[window_key]; } async function get_project_paths() { var project_paths = (await get_projects() || []).map((p)=&gt;{return p.path_with_namespace}); return project_paths; } function findmatches(items, q) { if(!items){ return []; } var i,item, re = new RegExp((&apos;&apos;+q).replace(/\s+/g,&apos; &apos;).replace(/[^0-9A-Z-a-z ]/g,&apos;.&apos;).replace(/[ ]/g,&apos;.*&apos;), &apos;i&apos;); console.log(q); console.log(re); console.log(items); var matches = []; for (i=0; i&lt;items.length; i++) { item = (&apos;&apos;+items[i]); if(item.match(re)) { matches.push(item); } } if (!matches.length) { matches = items; } var matches_weighed = matches.map(function(item){ return { q: q, item: item, ldist: levenshteinDistance2(q, item, { cost_substitution: 2, cost_insertion: 1, cost_deletion: 3, }), }; });...

JavaScript

async function load_projects() {
	// NB: this only works if we never get more than 100 projects (currently 73), the oldest are on next pages and will then be missing.
	// per_page has a maximum of 100
//	var response = await fetch('https://orange.dev/api/v4/projects?per_page=100');
//	return await response.json();
	// Also note, when doing cross domain requests to orange.dev/api apparently we only get max 3 results per page.

	var items = [], response, data, per_page = 100, page = 1, next_page, url;
	while(true) {
		console.log('---');
		var url = 'https://orange.dev/api/v4/projects?per_page='+per_page+'&page='+page;
		console.log(url);
		response = await fetch(url);
//		console.log({response});
		data = await response.json();
//		console.log({data});

		if(data && Array.isArray(data)) {
			items = items.concat(data);
		}
		next_page = await response.headers.get('X-Next-Page');
//		console.log({next_page});
		if(next_page > page) {
			page = next_page;
			// continue to next loop.
		} else {
			break;
		}
	}
	return data;
}

async function get_projects() {
	var window_key = '__tmp__gitlab_projects_orange_dev';
	if (!window[window_key]) {
		window[window_key] = await load_projects();
	}
	return window[window_key];
}
async function get_project_paths() {
	var project_paths = (await get_projects() || []).map((p)=>{return p.path_with_namespace});
//	console.log(project_paths);
	return project_paths;
}

function findmatches(items, q) {
	if(!items){
		return [];
	}
	var i,item, re = new RegExp((''+q).replace(/\s+/g,' ').replace(/[^0-9A-Z-a-z ]/g,'.').replace(/[ ]/g,'.*'), 'i');
	console.log(q);
	console.log(re);
	console.log(items);
	var matches = [];
	for (i=0; i<items.length; i++) {
		item = (''+items[i]);
		if(item.match(re)) {
			matches.push(item);
		}
	}
//	return matches;

	if (!matches.length) {
		// if no matches found, try to find best match from levenshteinDistance() (could be garbage, but probably better than nothing?)
		matches = items;
	}

	var...