Commit 336db8c8 authored by Robert Knight's avatar Robert Knight

Add a mechansim to allow the browser extension to pass config info to the app

Provide a way for the browser extension to pass config info to the app,
by running a content script which injects a <meta> tag into the page
with this form:

  <meta name="hypothesis-config" content="<JSON data>">

This configuration info is then merged with the result of the
hypothesisConfig() function, with the hypothesisConfig() function taking
priority.
parent 25b2516d
'use strict'; 'use strict';
var annotationIDs = require('../util/annotation-ids'); var annotationIDs = require('../util/annotation-ids');
var settings = require('../settings');
var docs = 'https://h.readthedocs.org/en/latest/hacking/customized-embedding.html'; var docs = 'https://h.readthedocs.org/en/latest/hacking/customized-embedding.html';
...@@ -15,15 +16,12 @@ function config(window_) { ...@@ -15,15 +16,12 @@ function config(window_) {
document.querySelector('link[type="application/annotator+html"]').href, document.querySelector('link[type="application/annotator+html"]').href,
}; };
// Parse config from `<meta name="hypothesis-config" content="<JSON>">` tags // Parse config from `<script class="js-hypothesis-config">` tags
var configElement = window_.document try {
.querySelector('meta[name="hypothesis-config"]'); Object.assign(options, settings(window_.document, 'js-hypothesis-config'));
if (configElement) { } catch (err) {
try { console.warn('Could not parse settings from js-hypothesis-config tags',
Object.assign(options, JSON.parse(configElement.content)); err);
} catch (err) {
console.warn('Could not parse Hypothesis config from', configElement);
}
} }
// Parse config from `window.hypothesisConfig` function // Parse config from `window.hypothesisConfig` function
......
...@@ -3,26 +3,32 @@ ...@@ -3,26 +3,32 @@
var config = require('../config'); var config = require('../config');
describe('annotator configuration', function () { describe('annotator configuration', function () {
var fakeMetaConfig; var fakeScriptConfig;
function fakeQuerySelector(selector) {
if (selector === 'link[type="application/annotator+html"]') {
return {href: 'app.html'};
} else if (selector === 'script.js-hypothesis-config' &&
fakeScriptConfig) {
return {textContent: fakeScriptConfig};
} else {
return null;
}
}
var fakeWindowBase = { var fakeWindowBase = {
document: { document: {
querySelector: sinon.spy(function (selector) { querySelector: fakeQuerySelector,
if (selector === 'link[type="application/annotator+html"]') { querySelectorAll: function (selector) {
return {href: 'app.html'}; var match = fakeQuerySelector(selector);
} else if (selector === 'meta[name="hypothesis-config"]' && return match ? [match] : [];
fakeMetaConfig) { },
return {content:fakeMetaConfig};
} else {
return null;
}
}),
}, },
location: {hash: ''}, location: {hash: ''},
}; };
beforeEach(function () { beforeEach(function () {
fakeMetaConfig = ''; fakeScriptConfig = '';
}); });
it('reads the app src from the link tag', function () { it('reads the app src from the link tag', function () {
...@@ -59,7 +65,7 @@ describe('annotator configuration', function () { ...@@ -59,7 +65,7 @@ describe('annotator configuration', function () {
}); });
it('merges the config from the "hypothesis-config" meta tag', function () { it('merges the config from the "hypothesis-config" meta tag', function () {
fakeMetaConfig = '{"annotations":"456"}'; fakeScriptConfig = '{"annotations":"456"}';
assert.deepEqual(config(fakeWindowBase), { assert.deepEqual(config(fakeWindowBase), {
app: 'app.html', app: 'app.html',
annotations: '456', annotations: '456',
......
...@@ -6,16 +6,20 @@ require('core-js/fn/object/assign'); ...@@ -6,16 +6,20 @@ require('core-js/fn/object/assign');
* Return application configuration information from the host page. * Return application configuration information from the host page.
* *
* Exposes shared application settings, read from script tags with the * Exposes shared application settings, read from script tags with the
* class 'js-hypothesis-settings' which contain JSON content. * class `settingsClass` which contain JSON content.
* *
* If there are multiple such tags, the configuration from each is merged. * If there are multiple such tags, the configuration from each is merged.
* *
* @param {Document|Element} document - The root element to search for * @param {Document|Element} document - The root element to search for
* <script> settings tags. * <script> settings tags.
* @param {string} settingsClass - The class name to match on <script> tags.
*/ */
function settings(document) { function settings(document, settingsClass) {
if (!settingsClass) {
settingsClass = 'js-hypothesis-settings';
}
var settingsElements = var settingsElements =
document.querySelectorAll('script.js-hypothesis-settings'); document.querySelectorAll('script.' + settingsClass);
var config = {}; var config = {};
for (var i=0; i < settingsElements.length; i++) { for (var i=0; i < settingsElements.length; i++) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment