Skip to content

Instantly share code, notes, and snippets.

@nicholasjhenry
Created January 12, 2022 20:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicholasjhenry/92f326c0799936c16943a8d03fdb0270 to your computer and use it in GitHub Desktop.
Save nicholasjhenry/92f326c0799936c16943a8d03fdb0270 to your computer and use it in GitHub Desktop.
Notes for an annotation SDK

Updated Instructions

Updated instructions for "small tweaks to the Hypothesis client" outlined in Notes for an annotation SDK.

  1. Clone the Hypothesis client: https://github.com/hypothesis/client

  2. Clone the Hypothesis browser extension: https://github.com/hypothesis/browser-extension

  3. Edit browser-extension/gulpfile.js adding const IS_PRODUCTION_BUILD = false. This turns off minification so it’s possible to read and debug the client code.

  4. Establish a link between the client and browser-extension repos (see more details in references below):

    client$ yarn link
    browser-extension$ yarn link hypothesis
    browser-extension$ make build SETTINGS_FILE=settings/chrome-prod.json
    # If you need to unlink:
    browser-extension$ yarn unlink hypothesis
  5. Build the Chrome browser extension that authenticates to the Hypothesis production service.

    browser-extension$ make build SETTINGS_FILE=settings/chrome-prod.json
  6. In a Chromium browser (e.g. Chrome or Edge or Brave) use chrome://extensions, click Load unpacked, and point to the browser-extension/build directory where you built the extension.

Make the changes shown in patches.js

Patches Summary

browser-extension/build

  • In options/index.html I added an input box to name an alternate server.
  • In options/options.js I sync that value to the cloud and also to the browser’s localStorage.
  • In the extension bundle I check localStorage for an alternate server and, if present, modify the API request used by the extension to show the number of notes found for a page.

browser-extension/build/client/build/scripts

  • In the sidebar bundle I check localStorage for an alternate server and, if present, modify the API requests used to search for, create, update, and delete annotations.

References

// browser-extension/build/extension.bundle.js
async function fetchAnnotationCount(uri) {
const altServer = localStorage.getItem('hypothesis.altServer')
const apiUrl = altServer ? `http://${altServer}` : 'https://hypothes.is/api'
const queryUrl = `${apiUrl}/badge?uri=${encodeUriQuery(uri)}`
console.log(queryUrl)
const response = await fetch(queryUrl, {
credentials: 'include'
});
const data = await response.json();
if (data && typeof data.total === 'number') {
return data.total;
}
throw new Error('Unable to parse badge response');
}
// browser-extension/build/client/build/scripts/sidebar.bundle.js
let newApiUrl
const altServer = localStorage.getItem('hypothesis.altServer')
if (altServer && apiUrl.pathname === '/api/search') {
newApiUrl = new URL(`https://${altServer}/search`)
newApiUrl.search = apiUrl.search
apiUrl = newApiUrl
}
if (altServer && apiUrl.pathname === '/api/annotations') {
newApiUrl = new URL(`https://${altServer}/create_annotation`)
apiUrl = newApiUrl
}
const match = apiUrl.pathname.match(/\/api\/(annotations\/\d+)/)
if (altServer && match) {
newApiUrl = new URL(`https://${altServer}/${match[1]}`)
apiUrl = newApiUrl
}
return fetch(apiUrl.toString(), {
// ...
}
let newApiUrl
const altServer = localStorage.getItem('hypothesis.altServer')
if (altServer && apiURL.pathname === '/api/search') {
newApiUrl = new URL(`http://${altServer}/search`)
newApiUrl.search = apiURL.search
apiURL = newApiUrl
}
if (altServer && apiURL.pathname === '/api/annotations') {
newApiUrl = new URL(`http://${altServer}/create_annotation`)
apiURL = newApiUrl
}
const match = apiURL.pathname.match(/\/api\/(annotations\/\d+)/)
if (altServer && match) {
newApiUrl = new URL(`http://${altServer}/${match[1]}`)
apiURL = newApiUrl
}
// browser-extension/build/options/index.html
<p>Alternate server</p>
<div>
<input id="altServer"></input>
</div>
// browser-extension/build/options/options.js
function altServerInput() {
return document.getElementById('altServer')
}
function saveOptions() {
const altServerInputValue = altServerInput().value === 'undefined' ? '' : altServerInput().value
chrome.storage.sync.set({
badge: badgeCheckbox().checked,
altServer: altServerInputValue
});
localStorage.setItem('hypothesis.altServer', altServerInputValue)
}
function loadOptions() {
chrome.storage.sync.get( {
badge: true,
altServer: ''
},
function (items) {
console.log(items)
badgeCheckbox().checked = items.badge
altServerInput().value = items.altServer
}
);
}
document.addEventListener('DOMContentLoaded', loadOptions);
badgeCheckbox().addEventListener('click', saveOptions);
altServerInput().addEventListener('change', saveOptions);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment