Commit bed7375a authored by Robert Knight's avatar Robert Knight

Extract `normalizeURI` function into a utility module

Extract the existing `normalizeURI` function from guest.coffee into a
utility module and re-use it in document.coffee to convert relative URLs
to absolute ones.

Also implement some direct tests for this function.
parent e160c23f
baseURI = require('document-base-uri')
extend = require('extend')
raf = require('raf')
scrollIntoView = require('scroll-into-view')
......@@ -12,6 +11,7 @@ highlighter = require('./highlighter')
rangeUtil = require('./range-util')
selections = require('./selections')
xpathRange = require('./anchoring/range')
{ normalizeURI } = require('./util/url')
animationPromise = (fn) ->
return new Promise (resolve, reject) ->
......@@ -21,17 +21,6 @@ animationPromise = (fn) ->
catch error
reject(error)
# Normalize the URI for an annotation. This makes it absolute and strips
# the fragment identifier.
normalizeURI = (uri, baseURI) ->
# Convert to absolute URL
url = new URL(uri, baseURI)
# Remove the fragment identifier.
# This is done on the serialized URL rather than modifying `url.hash` due
# to a bug in Safari.
# See https://github.com/hypothesis/h/issues/3471#issuecomment-226713750
return url.toString().replace(/#.*/, '');
module.exports = class Guest extends Delegator
SHOW_HIGHLIGHTS_CLASS = 'annotator-highlights-always-on'
......@@ -140,7 +129,7 @@ module.exports = class Guest extends Delegator
return Promise.all([metadataPromise, uriPromise]).then ([metadata, href]) =>
return {
uri: normalizeURI(href, baseURI),
uri: normalizeURI(href),
metadata,
frameIdentifier: this.frameIdentifier
}
......
$ = require('jquery')
Plugin = require('../plugin')
baseURI = require('document-base-uri')
Plugin = require('../plugin')
{ normalizeURI } = require('../util/url')
###
** Adapted from:
** https://github.com/openannotation/annotator/blob/v1.2.x/src/plugin/document.coffee
......@@ -185,9 +186,7 @@ module.exports = class Document extends Plugin
# Hack to get a absolute url from a possibly relative one
_absoluteUrl: (url) ->
d = @document.createElement('a')
d.href = url
d.href
normalizeURI(url, @baseURI)
# Get the true URI record when it's masked via a different protocol.
# This happens when an href is set with a uri using the 'blob:' protocol
......
'use strict';
const { normalizeURI } = require('../url');
describe('annotator.util.url', () => {
describe('normalizeURI', () => {
it('resolves relative URLs against the provided base URI', () => {
const base = 'http://example.com';
assert.equal(normalizeURI('index.html', base), `${base}/index.html`);
});
it('resolves relative URLs against the document URI, if no base URI is provided', () => {
// Strip filename from base URI.
const base = document.baseURI.replace(/\/[^/]*$/, '');
assert.equal(normalizeURI('foo.html'), `${base}/foo.html`);
});
it('does not modify absolute URIs', () => {
const url = 'http://example.com/wibble';
assert.equal(normalizeURI(url), url);
});
it('removes the fragment identifier', () => {
const url = 'http://example.com/wibble#fragment';
assert.equal(normalizeURI(url), 'http://example.com/wibble');
});
[
'file:///Users/jane/article.pdf',
'doi:10.1234/4567',
].forEach(url => {
it('does not modify absolute non-HTTP/HTTPS URLs', () => {
assert.equal(normalizeURI(url), url);
});
});
});
});
'use strict';
const baseURI = require('document-base-uri');
/**
* Return a normalized version of a URI.
*
* This makes it absolute and strips the fragment identifier.
*
* @param {string} uri - Relative or absolute URL
* @param {string} [base] - Base URL to resolve relative to. Defaults to
* the document's base URL.
*/
function normalizeURI(uri, base = baseURI) {
const absUrl = new URL(uri, base).href;
// Remove the fragment identifier.
// This is done on the serialized URL rather than modifying `url.hash` due to
// a bug in Safari.
// See https://github.com/hypothesis/h/issues/3471#issuecomment-226713750
return absUrl.toString().replace(/#.*/, '');
}
module.exports = {
normalizeURI,
};
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