diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index aabb829..20003ec 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -10,5 +10,13 @@
"appDescription": {
"message": "Browser extension to bookmark fragments of audio files",
"description": "The description of the application"
+ },
+ "bookmarkSelectionContextMenuItemForFragment": {
+ "message": "Bookmark selected fragment",
+ "description": "The entry in the context ('right-click') menu when selecting an audio fragment"
+ },
+ "bookmarkSelectionContextMenuItemForSingleMoment": {
+ "message": "Bookmark selected moment",
+ "description": "The entry in the context ('right-click') menu when selecting a single moment"
}
}
diff --git a/app/assets/main.css b/app/assets/main.css
index aec3371..a7edbda 100644
--- a/app/assets/main.css
+++ b/app/assets/main.css
@@ -85,3 +85,25 @@ input#volume:focus {
filter: brightness(102%);
outline: none;
}
+
+.context-menu {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ position: absolute;
+ z-index: 9999999;
+ border: 1px solid #99999966;
+ border-radius: 2px;
+ box-shadow: 2px 2px 6px #99999966;
+ background: #fcfcfc;
+}
+
+.context-menu button {
+ background: none;
+ border: none;
+ font-size: 1em;
+ padding: 4px 20px;
+}
+.context-menu button:hover {
+ background: #dddddd99;
+}
diff --git a/app/audio-player/contentscript.js b/app/audio-player/contentscript.js
index 14da539..9498132 100644
--- a/app/audio-player/contentscript.js
+++ b/app/audio-player/contentscript.js
@@ -76,6 +76,11 @@ async function init() {
// Start playing. A tiny delay seems needed in Firefox to show the cursor at the right place.
requestAnimationFrame(() => eventEmitter.emit('play'));
+
+ return playlist;
}
-init();
+init().then(playlist => {
+ // Store playlist as a shared global variable.
+ self.playlist = playlist;
+});
diff --git a/app/create-bookmarks/background.js b/app/create-bookmarks/background.js
new file mode 100644
index 0000000..094fc25
--- /dev/null
+++ b/app/create-bookmarks/background.js
@@ -0,0 +1,34 @@
+import { makeRemotelyCallable } from 'webextension-rpc';
+
+// Format time as S, or M:SS, or H:MM:SS, depending on which would be needed to express maxSeconds.
+// E.g. secondsToString(12) === '12', but secondsToString(12, 3600) === '0:00:12'.
+function secondsToString(seconds, maxSeconds) {
+ let s = `${Math.round(seconds % 60)}`;
+ let m = '';
+ let h = '';
+ const minutes = Math.floor(seconds / 60);
+ if (minutes || maxSeconds >= 60) {
+ m = `${minutes % 60}:`;
+ if (!/^\d\d/.test(s)) s = '0' + s;
+ }
+ if (seconds >= 60 * 60 || maxSeconds >= 60 * 60) {
+ h = `${Math.floor(minutes / 60)}:`;
+ if (m.length <= 2) m = '0' + m;
+ }
+ return `${h}${m}${s}`;
+}
+
+async function createBookmark({ url, start, end, trackDuration }) {
+ // Create a (hopefully) meaningful title; e.g. 'filename.mp3 0:30–1:10'
+ const filenameMatch = url.match(/.*\/([^\/#?]+)(?:\?.*)?(?:#.*)?/);
+ const filename = filenameMatch ? filenameMatch[1] : 'Audio fragment';
+ const startString = secondsToString(start, trackDuration);
+ const endString = (end !== undefined)
+ ? '–' + secondsToString(end, trackDuration)
+ : '';
+ const title = `${filename} ${startString}${endString}`;
+
+ await browser.bookmarks.create({ url, title });
+}
+
+makeRemotelyCallable({ createBookmark });
diff --git a/app/create-bookmarks/contentscript.js b/app/create-bookmarks/contentscript.js
new file mode 100644
index 0000000..9b4b1f4
--- /dev/null
+++ b/app/create-bookmarks/contentscript.js
@@ -0,0 +1,88 @@
+import html from 'nanohtml';
+import { remoteFunction } from 'webextension-rpc';
+
+import { createMediaFragmentIdentifier } from '../util/media-fragment-identifier';
+
+function createPreciseUrl(url, selector) {
+ const properUrl = url.split('#')[0];
+
+ let fragmentIdentifier;
+ if (selector.type === 'FragmentSelector') {
+ fragmentIdentifier = selector.value;
+ } else {
+ throw new Error('Unsupported selector type');
+ }
+
+ return properUrl + '#' + fragmentIdentifier;
+}
+
+function describeMediaFragment({ start, end }) {
+ const fragmentIdentifier = createMediaFragmentIdentifier({ start, end });
+
+ const selector = {
+ type: 'FragmentSelector',
+ conformsTo: 'http://www.w3.org/TR/media-frags/',
+ value: fragmentIdentifier,
+ };
+ return selector;
+}
+
+async function init() {
+ let menuEl;
+
+ function hideMenu() {
+ if (!menuEl) return;
+ menuEl.parentNode.removeChild(menuEl);
+ menuEl = undefined;
+ }
+
+ function onContextMenu(event) {
+ event.preventDefault();
+ const left = event.pageX;
+ const top = event.pageY;
+
+ const playlist = self.playlist;
+ if (!playlist) {
+ throw new Error('Player has not been initialised.');
+ }
+ const trackDuration = playlist.duration;
+ let { start, end } = playlist.getTimeSelection();
+ if (start === undefined) return;
+
+ // Waveform Playlist tells us end=start when the selection is just a single line.
+ if (end === start) end = undefined;
+
+ // Round the numbers to two decimals.
+ // Also, as Waveform Playlist might report a slightly negative number, first cap it to zero.
+ start = Math.round(Math.max(0, start) * 100) / 100;
+ if (end !== undefined) end = Math.round(Math.max(0, end) * 100) / 100;
+
+ async function createBookmark() {
+ const fileUrl = document.URL;
+ const selector = describeMediaFragment({ start, end });
+ const bookmarkUrl = createPreciseUrl(fileUrl, selector);
+ await remoteFunction('createBookmark')({ url: bookmarkUrl, start, end, trackDuration });
+ }
+
+ hideMenu();
+ menuEl = html`
+
+ `;
+ document.body.appendChild(menuEl);
+ }
+
+ document.addEventListener('contextmenu', onContextMenu, false);
+
+ document.addEventListener('click', event => { hideMenu(); });
+}
+
+init();
diff --git a/app/manifest.json b/app/manifest.json
index dcef13b..d11f6fe 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -10,6 +10,8 @@
},
"permissions": [
"",
+ "bookmarks",
+ "tabs",
"webRequest"
]
}
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 8663d22..a5866e1 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -1 +1,2 @@
import '../audio-player/background.js'
+import '../create-bookmarks/background.js'
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js
index e33d912..ccccdce 100644
--- a/app/scripts/contentscript.js
+++ b/app/scripts/contentscript.js
@@ -1 +1,2 @@
import '../audio-player/contentscript.js'
+import '../create-bookmarks/contentscript.js'
diff --git a/package-lock.json b/package-lock.json
index 8967650..8d94cd1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1306,6 +1306,28 @@
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
"dev": true
},
+ "acorn-node": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
+ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
+ "requires": {
+ "acorn": "^7.0.0",
+ "acorn-walk": "^7.0.0",
+ "xtend": "^4.0.2"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
+ "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ=="
+ }
+ }
+ },
+ "acorn-walk": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.0.0.tgz",
+ "integrity": "sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg=="
+ },
"ajv": {
"version": "6.10.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
@@ -2298,6 +2320,11 @@
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
"dev": true
},
+ "browser-process-hrtime": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
+ "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw=="
+ },
"browser-split": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/browser-split/-/browser-split-0.0.1.tgz",
@@ -2518,6 +2545,15 @@
"integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=",
"dev": true
},
+ "camel-case": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.1.1"
+ }
+ },
"camelcase": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
@@ -2942,7 +2978,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
"integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
- "dev": true,
"requires": {
"safe-buffer": "~5.1.1"
}
@@ -3016,8 +3051,7 @@
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
- "dev": true
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"create-ecdh": {
"version": "4.0.3",
@@ -3116,6 +3150,11 @@
"type": "^1.0.1"
}
},
+ "dash-ast": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
+ "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA=="
+ },
"date-now": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
@@ -3563,8 +3602,7 @@
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"eslint-scope": {
"version": "4.0.3",
@@ -3624,6 +3662,11 @@
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
+ "estree-is-member-expression": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/estree-is-member-expression/-/estree-is-member-expression-1.0.0.tgz",
+ "integrity": "sha512-Ec+X44CapIGExvSZN+pGkmr5p7HwUVQoPQSd458Lqwvaf4/61k/invHSh4BYK8OXnCkfEhWuIoG5hayKLQStIg=="
+ },
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -4823,6 +4866,21 @@
"function-bind": "^1.1.1"
}
},
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ }
+ }
+ },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -4946,6 +5004,19 @@
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
"dev": true
},
+ "hyperscript-attribute-to-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hyperscript-attribute-to-property/-/hyperscript-attribute-to-property-1.0.2.tgz",
+ "integrity": "sha512-oerMul16jZCmrbNsUw8QgrtDzF8lKgFri1bKQjReLw1IhiiNkI59CWuzZjJDGT79UQ1YiWqXhJMv/tRMVqgtkA=="
+ },
+ "hyperx": {
+ "version": "2.5.4",
+ "resolved": "https://registry.npmjs.org/hyperx/-/hyperx-2.5.4.tgz",
+ "integrity": "sha512-iOkSh7Yse7lsN/B9y7OsevLWjeXPqGuHQ5SbwaiJM5xAhWFqhoN6erpK1dQsS12OFU36lyai1pnx1mmzWLQqcA==",
+ "requires": {
+ "hyperscript-attribute-to-property": "^1.0.0"
+ }
+ },
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
@@ -5082,8 +5153,7 @@
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
"version": "1.3.5",
@@ -5152,6 +5222,11 @@
"binary-extensions": "^1.0.0"
}
},
+ "is-boolean-attribute": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-attribute/-/is-boolean-attribute-0.0.1.tgz",
+ "integrity": "sha1-JKtZt9y52jYSx3PmDGVlZeWgmAw="
+ },
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -5423,8 +5498,7 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isemail": {
"version": "3.2.0",
@@ -5674,6 +5748,11 @@
"signal-exit": "^3.0.2"
}
},
+ "lower-case": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
+ },
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
@@ -5690,6 +5769,14 @@
"yallist": "^2.1.2"
}
},
+ "magic-string": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.23.2.tgz",
+ "integrity": "sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA==",
+ "requires": {
+ "sourcemap-codec": "^1.4.1"
+ }
+ },
"make-dir": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
@@ -5808,6 +5895,14 @@
}
}
},
+ "merge-source-map": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz",
+ "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=",
+ "requires": {
+ "source-map": "^0.5.6"
+ }
+ },
"merge2": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz",
@@ -5991,6 +6086,11 @@
"resolved": "https://registry.npmjs.org/mucss/-/mucss-1.1.5.tgz",
"integrity": "sha1-fNbsWVWQ5gPkg6ENaajsfdJwplY="
},
+ "mutexify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.2.0.tgz",
+ "integrity": "sha512-oprzxd2zhfrJqEuB98qc1dRMMonClBQ57UPDjnbcrah4orEMTq1jq3+AcdFe5ePzdbJXI7zmdhfftIdMnhYFoQ=="
+ },
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
@@ -5998,6 +6098,77 @@
"dev": true,
"optional": true
},
+ "nanoassert": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz",
+ "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40="
+ },
+ "nanobench": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nanobench/-/nanobench-2.1.1.tgz",
+ "integrity": "sha512-z+Vv7zElcjN+OpzAxAquUayFLGK3JI/ubCl0Oh64YQqsTGG09CGqieJVQw4ui8huDnnAgrvTv93qi5UaOoNj8A==",
+ "requires": {
+ "browser-process-hrtime": "^0.1.2",
+ "chalk": "^1.1.3",
+ "mutexify": "^1.1.0",
+ "pretty-hrtime": "^1.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ }
+ }
+ },
+ "nanohtml": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/nanohtml/-/nanohtml-1.8.1.tgz",
+ "integrity": "sha512-yoS1g5rikfacn4XA9dgr2GHO5oVUImFdnKjFrnLLZtmM+73CCM4yWK8NalD8HwTvK8a6d3vV2+GVzcoHrC83WQ==",
+ "requires": {
+ "acorn-node": "^1.8.2",
+ "camel-case": "^3.0.0",
+ "convert-source-map": "^1.5.1",
+ "estree-is-member-expression": "^1.0.0",
+ "hyperx": "^2.5.0",
+ "is-boolean-attribute": "0.0.1",
+ "nanoassert": "^1.1.0",
+ "nanobench": "^2.1.0",
+ "normalize-html-whitespace": "^0.2.0",
+ "through2": "^2.0.3",
+ "transform-ast": "^2.4.0"
+ }
+ },
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -6028,6 +6199,14 @@
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
},
+ "no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "requires": {
+ "lower-case": "^1.1.1"
+ }
+ },
"node-libs-browser": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
@@ -6090,6 +6269,11 @@
}
}
},
+ "normalize-html-whitespace": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/normalize-html-whitespace/-/normalize-html-whitespace-0.2.0.tgz",
+ "integrity": "sha1-EBci9kI1Ucdc24+dEE/4UNrx4Q4="
+ },
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -6594,6 +6778,11 @@
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
"dev": true
},
+ "pretty-hrtime": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
+ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE="
+ },
"pretty-ms": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-5.0.0.tgz",
@@ -6623,8 +6812,7 @@
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"promise-inflight": {
"version": "1.0.1",
@@ -6770,7 +6958,6 @@
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
- "dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -7046,8 +7233,7 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safe-regex": {
"version": "1.1.0",
@@ -7302,8 +7488,7 @@
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"source-map-resolve": {
"version": "0.5.2",
@@ -7342,6 +7527,11 @@
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
"dev": true
},
+ "sourcemap-codec": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
+ "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg=="
+ },
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@@ -7522,7 +7712,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
"requires": {
"safe-buffer": "~5.1.0"
}
@@ -7799,7 +7988,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
- "dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
@@ -7897,6 +8085,27 @@
}
}
},
+ "transform-ast": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/transform-ast/-/transform-ast-2.4.4.tgz",
+ "integrity": "sha512-AxjeZAcIOUO2lev2GDe3/xZ1Q0cVGjIMk5IsriTy8zbWlsEnjeB025AhkhBJHoy997mXpLd4R+kRbvnnQVuQHQ==",
+ "requires": {
+ "acorn-node": "^1.3.0",
+ "convert-source-map": "^1.5.1",
+ "dash-ast": "^1.0.0",
+ "is-buffer": "^2.0.0",
+ "magic-string": "^0.23.2",
+ "merge-source-map": "1.0.4",
+ "nanobench": "^2.1.1"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
+ }
+ }
+ },
"trim-newlines": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
@@ -8120,6 +8329,11 @@
}
}
},
+ "upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
+ },
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -8188,8 +8402,7 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"util.promisify": {
"version": "1.0.0",
@@ -8293,6 +8506,29 @@
"integrity": "sha512-ISB42vlgMyM7xE1u6pREeCqmmXjLsYu/nqAR8Dl/gIAnylb+KpRpvKbVkUYNFePhhXn0Obkkc3jasOII9ztUtg==",
"dev": true
},
+ "webextension-rpc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/webextension-rpc/-/webextension-rpc-0.1.0.tgz",
+ "integrity": "sha512-9JCBkXmeP7ossYauXgfvxqQurO5E0VK7uQnlIyirj1zzhGzV92TvOC4FhhqhYBphV9d0doUg+pCQtvRkGsk8+A==",
+ "requires": {
+ "@babel/runtime": "^7.6.2"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
+ "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
+ "requires": {
+ "regenerator-runtime": "^0.13.2"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
+ }
+ }
+ },
"webextension-toolbox": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/webextension-toolbox/-/webextension-toolbox-3.0.0.tgz",
diff --git a/package.json b/package.json
index 78dd204..4214d1c 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,9 @@
},
"dependencies": {
"delay": "^4.3.0",
- "waveform-playlist": "^3.0.4"
+ "nanohtml": "^1.8.1",
+ "waveform-playlist": "^3.0.4",
+ "webextension-rpc": "^0.1.0"
},
"ava": {
"require": [