Skip to content

Commit

Permalink
Move autodetect into binderhub-client
Browse files Browse the repository at this point in the history
  • Loading branch information
manics committed Dec 13, 2023
1 parent bad7744 commit da9639d
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 69 deletions.
48 changes: 26 additions & 22 deletions binderhub/static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
import ClipboardJS from "clipboard";
import "event-source-polyfill";

import { BinderRepository } from "@jupyterhub/binderhub-client";
import { BinderRepository, detect } from "@jupyterhub/binderhub-client";
import { updatePathText } from "./src/path";
import { nextHelpText } from "./src/loading";
import { updateFavicon } from "./src/favicon";
import { detect } from "./src/autodetect";

import "xterm/css/xterm.css";

Expand Down Expand Up @@ -175,28 +174,33 @@ function indexMain() {
?.getData("text")
.trim();
if (pastedText) {
const fields = detect(pastedText);
console.log(fields);
if (fields) {
$("#provider_prefix-selected").text(fields.display_name);
$("#provider_prefix").val(fields.provider);
$("#repository").val(fields.repo);
if (fields.ref) {
$("#ref").val(fields.ref);
event.preventDefault();
detect(BASE_URL, pastedText).then((fields) => {
console.log(fields);
if (fields) {
$("#provider_prefix-selected").text(fields.displayName);
$("#provider_prefix").val(fields.providerPrefix);
$("#repository").val(fields.repository);
if (fields.ref) {
$("#ref").val(fields.ref);
}
if (fields.path) {
$("#filepath").val(fields.path);
$("#url-or-file-selected").text(
fields.pathType === "filepath" ? "File" : "URL",
);
}
updatePathText();
// updateRepoText(BASE_URL);
} else {
// else autodetect failed, paste the original
$("#repository").val(pastedText);
}
if (fields.path) {
$("#filepath").val(fields.path);
$("#url-or-file-selected").text(
fields.pathType === "filepath" ? "File" : "URL",
);
}
updatePathText();
event.preventDefault();
updateRepoText(BASE_URL);
}
updateUrls(BADGE_BASE_URL);
});
} else {
updateUrls(BADGE_BASE_URL);
}
// else autodetect failed, let the paste go through
updateUrls(BADGE_BASE_URL);
});

$("#repository").on("keyup change", function () {
Expand Down
27 changes: 0 additions & 27 deletions binderhub/static/js/src/autodetect.js

This file was deleted.

24 changes: 5 additions & 19 deletions binderhub/static/js/src/repo.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getRepoProviders } from "@jupyterhub/binderhub-client";

/**
* Dict holding cached values of API request to _config endpoint
* @param {Object} configDict Dict holding cached values of API request to _config endpoint
*/
let configDict = {};

function setLabels() {
function setLabels(configDict) {
const provider = $("#provider_prefix").val();
const text = configDict[provider]["text"];
const tagText = configDict[provider]["tag_text"];
Expand All @@ -23,19 +23,5 @@ function setLabels() {
* @param {URL} baseUrl Base URL to use for constructing path to _config endpoint
*/
export function updateRepoText(baseUrl) {
if (Object.keys(configDict).length === 0) {
const configUrl = new URL("_config", baseUrl);
fetch(configUrl).then((resp) => {
resp.json().then((data) => {
configDict = data;
setLabels();
});
});
} else {
setLabels();
}
}

export function getConfigDict() {
return configDict;
getRepoProviders(baseUrl).then(setLabels);
}
67 changes: 67 additions & 0 deletions js/packages/binderhub-client/lib/autodetect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { fetch as fetchPolyfill } from "whatwg-fetch";

// Use native browser fetch if available, and use the polyfill if not available
// (e.g. in tests https://github.com/jestjs/jest/issues/13834#issuecomment-1407375787)
// @todo: this is only a problem in the jest tests, so get rid of this and mock fetch instead
const fetch = window.fetch || fetchPolyfill;

/**
* Dict holding cached values of API request to _config endpoint
*/
let repoProviders = {};

/**
* Get the repo provider configurations supported by the BinderHub instance
*
* @param {URL} baseUrl Base URL to use for constructing path to _config endpoint
*/
export async function getRepoProviders(baseUrl) {
if (Object.keys(repoProviders).length === 0) {
const configUrl = new URL("_config", baseUrl);
const resp = await fetch(configUrl);
repoProviders = resp.json();
}
return repoProviders;
}

/**
* Attempt to parse a string (typically a repository URL) into a BinderHub
* provider/repository/reference/path
*
* @param {URL} baseUrl Base URL to use for constructing path to _config endpoint
* @param {string} text Repository URL or similar to parse
* @returns {Object} An object if the repository could be parsed with fields
* - providerPrefix Prefix denoting what provider was selected
* - repository Repository to build
* - ref Ref in this repo to build (optional)
* - path Path to launch after this repo has been built (optional)
* - pathType Type of thing to open path with (raw url, notebook file) (optional)
* - providerName User friendly display name of the provider (optional)
* null otherwise
*/
export async function detect(baseUrl, text) {
const config = await getRepoProviders(baseUrl);

for (const provider in config) {
const regex_detect = config[provider].regex_detect || [];
for (const regex of regex_detect) {
const m = text.match(regex);
if (m?.groups.repo) {
return {
providerPrefix: provider,
repository: m.groups.repo,
ref: m.groups.ref,
path: m.groups.filepath || m.groups.urlpath || null,
pathType: m.groups.filepath
? "filepath"
: m.groups.urlpath
? "urlpath"
: null,
providerName: config[provider].display_name,
};
}
}
}

return null;
}
4 changes: 4 additions & 0 deletions js/packages/binderhub-client/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { NativeEventSource, EventSourcePolyfill } from "event-source-polyfill";
import { EventIterator } from "event-iterator";

import { detect, getRepoProviders } from "./autodetect";

// Use native browser EventSource if available, and use the polyfill if not available
const EventSource = NativeEventSource || EventSourcePolyfill;

Expand Down Expand Up @@ -211,3 +213,5 @@ export function makeBadgeMarkup(publicBaseUrl, url, syntax) {
);
}
}

export { detect, getRepoProviders };
3 changes: 2 additions & 1 deletion js/packages/binderhub-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
},
"homepage": "https://github.com/jupyterhub/binderhub#readme",
"dependencies": {
"event-iterator": "^2.0.0",
"event-source-polyfill": "^1.0.31",
"event-iterator": "^2.0.0"
"whatwg-fetch": "^3.6.19"
}
}

0 comments on commit da9639d

Please sign in to comment.