diff --git a/app/audio-player/contentscript.js b/app/audio-player/contentscript.js index 510b9ef..14da539 100644 --- a/app/audio-player/contentscript.js +++ b/app/audio-player/contentscript.js @@ -1,7 +1,7 @@ import * as WaveformPlaylist from 'waveform-playlist'; import delay from 'delay'; -import parseMediaFragmentIdentifier from '../util/parse-media-fragment-identifier.js'; +import { parseMediaFragmentIdentifier } from '../util/media-fragment-identifier.js'; async function init() { document.body.innerHTML = ` diff --git a/app/util/parse-media-fragment-identifier.js b/app/util/media-fragment-identifier.js similarity index 64% rename from app/util/parse-media-fragment-identifier.js rename to app/util/media-fragment-identifier.js index 171f99e..1609626 100644 --- a/app/util/parse-media-fragment-identifier.js +++ b/app/util/media-fragment-identifier.js @@ -1,8 +1,20 @@ -// Parses the time range from a media fragment identifier such as '#t=12.5,1:59:45.12'. +// Functions for parsing and creating a media fragment identifiers. +// A media fragment is used to specify a time range of an audio/video track, e.g. #t=12,18.5. // See https://www.w3.org/TR/media-frags/ -// Note this only supports npt (normal playing time) format, not smpte or wall clock time. + +// Creates a media fragment identifier for a given time range (in seconds). +export function createMediaFragmentIdentifier({ start, end }) { + // Always output the time in seconds, as it is more widely supported than h:m:s syntax. + const maybeStart = start !== undefined ? start : ''; + const maybeEnd = end !== undefined ? `,${end}` : ''; + const fragmentIdentifier = `t=${maybeStart}${maybeEnd}`; + return fragmentIdentifier; +} + +// Parses the time range from a media fragment identifier. // Returns an object { start, end }; both numbers are given in seconds (possibly non-integer). -export default function parseMediaFragmentIdentifier(fragmentIdentifier) { +// Note this only supports the usual npt (normal playing time) format, not smpte or wall clock time. +export function parseMediaFragmentIdentifier(fragmentIdentifier) { // Strip possible leading hash character '#'. if (fragmentIdentifier.startsWith('#')) { fragmentIdentifier = fragmentIdentifier.substring(1); diff --git a/app/util/parse-media-fragment-identifier.test.js b/app/util/media-fragment-identifier.test.js similarity index 59% rename from app/util/parse-media-fragment-identifier.test.js rename to app/util/media-fragment-identifier.test.js index f026e72..95ee565 100644 --- a/app/util/parse-media-fragment-identifier.test.js +++ b/app/util/media-fragment-identifier.test.js @@ -1,8 +1,18 @@ import test from 'ava'; -import parse from './parse-media-fragment-identifier.js'; +import { + createMediaFragmentIdentifier, + parseMediaFragmentIdentifier, +} from './media-fragment-identifier.js'; -const inputResultPairs = { +const creatorResultInputPairs = { + 't=12.345,67.89': { start: 12.345, end: 67.89 }, + 't=,67.89': { end: 67.89 }, + 't=0,67.89': { start: 0, end: 67.89 }, + 't=12.345': { start: 12.345 }, +}; + +const parserInputResultPairs = { 't=1,2': { start: 1, end: 2 }, 't=npt:1,2': { start: 1, end: 2 }, 't=,2': { start: 0, end: 2 }, @@ -27,10 +37,18 @@ const inputResultPairs = { 't=10%2C20': { start: 10, end: 20 }, 't=%6ept:10': { start: 10, end: undefined }, 't=npt%3a10': { start: 10, end: undefined }, +}; + +// Test creating. +for (const [expectedResult, input] of Object.entries(creatorResultInputPairs)) { + test(`Correctly create fragment '${expectedResult}'`, t => { + t.is(createMediaFragmentIdentifier(input), expectedResult); + }); } -for (const [input, expectedResult] of Object.entries(inputResultPairs)) { +// Test parsing. +for (const [input, expectedResult] of Object.entries(parserInputResultPairs)) { test(`Correctly parse input '${input}'`, t => { - t.deepEqual(parse(input), expectedResult); + t.deepEqual(parseMediaFragmentIdentifier(input), expectedResult); }); }