-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
140 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* See also: https://www.w3.org/TR/media-frags/#valid-uri | ||
*/ | ||
export default { | ||
tFrag: /(?<start>[\w:\.]*?)(?:,(?<end>[\w:\.]+?))?$/, | ||
|
||
npt_sec: /^\d+(?:\.\d+)?$/, | ||
npt_mmss: /^(?<mm>[0-5]\d):(?<ss>[0-5]\d(?:\.\d+)?)$/, | ||
npt_hhmmss: /^(?<hh>\d+):(?<mm>[0-5]\d):(?<ss>[0-5]\d(?:\.\d+)?)$/, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { parseUrl, parse, ParsedQuery } from "query-string"; | ||
import MFDefs from "./MFDefs"; | ||
|
||
export function parseHash(url: string): ParsedQuery | null { | ||
const hash = parseUrl(url, { parseFragmentIdentifier: true }).fragmentIdentifier; | ||
if (hash) { | ||
return parse(hash); | ||
} else { | ||
return null; | ||
} | ||
} | ||
export function parseTF(hash: string | undefined): TimeSpan | null { | ||
if (hash) { | ||
const params = parse(hash); | ||
const paramT = params.t; | ||
let match; | ||
if (paramT && typeof paramT === "string" && (match = MFDefs.tFrag.exec(paramT)) !== null) { | ||
if (!match.groups) | ||
throw new Error("tFragRegex match error"); | ||
const { start, end } = match.groups; | ||
const timeSpan = getTimeSpan(start, end); | ||
if (timeSpan) | ||
return { ...timeSpan, raw: paramT }; | ||
else | ||
return null; | ||
} | ||
} | ||
return null; | ||
} | ||
export function bindTimeSpan(timeSpan: TimeSpan, player: HTMLMediaElement) { | ||
if (timeSpan.end !== Infinity) { | ||
player.ontimeupdate = function (e) { | ||
const p = this as HTMLMediaElement; | ||
if (p.currentTime >= timeSpan.end) { | ||
p.pause(); | ||
p.ontimeupdate = null; | ||
} | ||
}; | ||
} | ||
player.currentTime = timeSpan.start; | ||
if (player.paused) | ||
player.play(); | ||
} | ||
interface TimeSpan { | ||
end: number; | ||
start: number; | ||
/** | ||
* raw value of key "t" in #t={value} | ||
*/ | ||
raw: string; | ||
} | ||
function getTimeSpan( | ||
start: string | undefined, | ||
end: string | undefined | ||
): Omit<TimeSpan, "raw"> | null { | ||
// start may be an empty string | ||
const startRaw = start ? start : null; | ||
const endRaw = end ?? null; | ||
|
||
let startTime, endTime; | ||
if (startRaw && endRaw) { | ||
startTime = convertTime(startRaw); | ||
endTime = convertTime(endRaw); | ||
} else if (startRaw) { | ||
startTime = convertTime(startRaw); | ||
endTime = Infinity; | ||
} else if (endRaw) { | ||
startTime = 0; | ||
endTime = convertTime(endRaw); | ||
} else { | ||
throw new Error("Missing startTime and endTime"); | ||
} | ||
|
||
if (startTime === null || endTime === null) { | ||
return null; | ||
} else { | ||
return { start: startTime, end: endTime }; | ||
} | ||
} | ||
function convertTime(input: string): number | null { | ||
const npttimedef = /^(?:npt:)?([\d\.:]+)$/; | ||
if (npttimedef.test(input)) { | ||
const rawTime = (input.match(npttimedef) as RegExpMatchArray)[1]; | ||
|
||
let match; | ||
|
||
if ((match = MFDefs.npt_sec.exec(rawTime)) !== null) { | ||
return +match[0]; | ||
} else if ((match = MFDefs.npt_mmss.exec(rawTime)) !== null) { | ||
if (!match.groups) | ||
throw new Error("npt_mmss match error"); | ||
const { mm, ss } = match.groups; | ||
return +mm * 60 + +ss; | ||
} else if ((match = MFDefs.npt_hhmmss.exec(rawTime)) !== null) { | ||
if (!match.groups) | ||
throw new Error("npt_hhmmss match error"); | ||
const { hh, mm, ss } = match.groups; | ||
return +hh * 60 + +mm * 60 + +ss; | ||
} else | ||
return null; | ||
} else { | ||
console.error("fail to parse npt: " + input); | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters