PageSourceSearch

https://www.kkth.at/swstatic-261006122627/swscripts/bower/dist/vid…/[email protected]/dist/prod/index.js

js kkth.at collected 2026-10-07 23:43:10 UTC 38,920 bytes, 1,324 lines download raw bytes

vendor: 4,722 bytes, lines 1-183
1const ParseErrorCode = {
2  LoadFail: 0,
3  BadSignature: 1,
4  BadTimestamp: 2,
5  BadSettingValue: 3,
6  BadFormat: 4,
7  UnknownSetting: 5
8};
9class ParseError extends Error {
10  code;
11  line;
12  constructor(init) {
13    super(init.reason);
14    this.code = init.code;
15    this.line = init.line;
16  }
17}
18
19const LINE_TERMINATOR_RE = /\r?\n|\r/gm;
20class TextLineTransformStream {
21  writable;
22  readable;
23  constructor(encoding) {
24    const transformer = new TextStreamLineIterator(encoding);
25    this.writable = new WritableStream({
26      write(chunk) {
27        transformer.transform(chunk);
28      },
29      close() {
30        transformer.close();
31      }
32    });
33    this.readable = new ReadableStream({
34      start(controller) {
35        transformer.onLine = (line) => controller.enqueue(line);
36        transformer.onClose = () => controller.close();
37      }
38    });
39  }
40}
41class TextStreamLineIterator {
42  x = "";
43  y;
44  onLine;
45  onClose;
46  constructor(encoding) {
47    this.y = new TextDecoder(encoding);
48  }
49  transform(chunk) {
50    this.x += this.y.decode(chunk, { stream: true });
51    const lines = this.x.split(LINE_TERMINATOR_RE);
52    this.x = lines.pop() || "";
53    for (let i = 0; i < lines.length; i++)
54      this.onLine(lines[i].trim());
55  }
56  close() {
57    if (this.x)
58      this.onLine(this.x.trim());
59    this.x = "";
60    this.onClose();
61  }
62}
63
64async function parseText(text, options) {
65  const stream = new ReadableStream({
66    start(controller) {
67      const lines = text.split(LINE_TERMINATOR_RE);
68      for (const line of lines)
69        controller.enqueue(line);
70      controller.close();
71    }
72  });
73  return parseTextStream(stream, options);
74}
75async function parseTextStream(stream, options) {
76  const type = options?.type ?? "vtt";
77  let factory;
78  if (typeof type === "string") {
79    switch (type) {
80      case "srt":
81        factory = (await import('./srt-parser.js')).default;
82        break;
83      case "ssa":
84      case "ass":
85        factory = (await import('./ssa-parser.js')).default;
86        break;
87      default:
88        factory = (await Promise.resolve().then(function () { return vttParser; })).default;
89    }
90  } else {
91    factory = type;
92  }
93  let result;
94  const reader = stream.getReader(), parser = factory(), errors = !!options?.strict || !!options?.errors;
95  await parser.init({
96    strict: false,
97    ...options,
98    errors,
99    type,
100    cancel() {
101      reader.cancel();
102      result = parser.done(true);
103    }
104  });
105  let i = 1;
106  while (true) {
107    const { value, done } = await reader.read();
108    if (done) {
109      parser.parse("", i);
110      result = parser.done(false);
111      break;
112    }
113    parser.parse(value, i);
114    i++;
115  }
116  return result;
117}
118
119async function parseResponse(response, options) {
120  const res = await response;
121  if (!res.ok || !res.body) {
122    let error;
123    return {
124      metadata: {},
125      cues: [],
126      regions: [],
127      errors: [error]
128    };
129  }
130  const contentType = res.headers.get("content-type") || "", type = contentType.match(/text\/(.*?)(?:;|$)/)?.[1], encoding = contentType.match(/charset=(.*?)(?:;|$)/)?.[1];
131  return parseByteStream(res.body, { type, encoding, ...options });
132}
133async function parseByteStream(stream, { encoding = "utf-8", ...options } = {}) {
134  const textStream = stream.pipeThrough(new TextLineTransformStream(encoding));
135  return parseTextStream(textStream, options);
136}
137
138class TextCue extends EventTarget {
139  /**
140   * A string that identifies the cue.
141   *
142   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/TextTrackCue/id}
143   */
144  id = "";
145  /**
146   * A `double` that represents the video time that the cue will start being displayed, in seconds.
147   *
148   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/TextTrackCue/startTime}
149   */
150  startTime;
151  /**
152   * A `double` that represents the video time that the cue will stop being displayed, in seconds.
153   *
154   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/TextTrackCue/endTime}
155   */
156  endTime;
157  /**
158   * Returns a string with the contents of the cue.
159   *
160   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/text}
161   */
162  text;
163  /**
164   * A `boolean` for whether the video will pause when this cue stops being displayed.
165   *
166   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/TextTrackCue/pauseOnExit}
167   */
168  pauseOnExit = false;
169  constructor(startTime, endTime, text) {
170    super();
171    this.startTime = startTime;
172    this.endTime = endTime;
173    this.text = text;
174  }
175  addEventListener(type, listener, options) {
176    super.addEventListener(type, listener, options);
177  }
178  removeEventListener(type, listener, options) {
179    super.removeEventListener(type, listener, options);
180  }
181}
182
183const 
183IS_SERVER = typeof document === "undefined";
184
185const CueBase = IS_SERVER ? TextCue :
vendor: 17,285 bytes, lines 185-782
185 window.VTTCue;
186class VTTCue extends CueBase {
187  /**
188   * A `VTTRegion` object describing the video's sub-region that the cue will be drawn onto,
189   * or `null` if none is assigned.
190   *
191   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/region}
192   */
193  region = null;
194  /**
195   * The cue writing direction.
196   *
197   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/vertical}
198   */
199  vertical = "";
200  /**
201   * Returns `true` if the `VTTCue.line` attribute is an integer number of lines or a percentage
202   * of the video size.
203   *
204   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/snapToLines}
205   */
206  snapToLines = true;
207  /**
208   * Returns the line positioning of the cue. This can be the string `'auto'` or a number whose
209   * interpretation depends on the value of `VTTCue.snapToLines`.
210   *
211   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/line}
212   */
213  line = "auto";
214  /**
215   * Returns an enum representing the alignment of the `VTTCue.line`.
216   *
217   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/lineAlign}
218   */
219  lineAlign = "start";
220  /**
221   * Returns the indentation of the cue within the line. This can be the string `'auto'` or a
222   * number representing the percentage of the `VTTCue.region`, or the video size if `VTTCue`.region`
223   * is `null`.
224   *
225   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/position}
226   */
227  position = "auto";
228  /**
229   * Returns an enum representing the alignment of the cue. This is used to determine what
230   * the `VTTCue.position` is anchored to. The default is `'auto'`.
231   *
232   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/positionAlign}
233   */
234  positionAlign = "auto";
235  /**
236   * Returns a double representing the size of the cue, as a percentage of the video size.
237   *
238   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/size}
239   */
240  size = 100;
241  /**
242   * Returns an enum representing the alignment of all the lines of text within the cue box.
243   *
244   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/VTTCue/align}
245   */
246  align = "center";
247  /**
248   * Additional styles associated with the cue.
249   */
250  style;
251}
252
253class VTTRegion {
254  /**
255   * A string that identifies the region.
256   */
257  id = "";
258  /**
259   * A `double` representing the width of the region, as a percentage of the video.
260   */
261  width = 100;
262  /**
263   * A `double` representing the height of the region, in number of lines.
264   */
265  lines = 3;
266  /**
267   * A `double` representing the region anchor X offset, as a percentage of the region.
268   */
269  regionAnchorX = 0;
270  /**
271   * A `double` representing the region anchor Y offset, as a percentage of the region.
272   */
273  regionAnchorY = 100;
274  /**
275   * A `double` representing the viewport anchor X offset, as a percentage of the video.
276   */
277  viewportAnchorX = 0;
278  /**
279   * A `double` representing the viewport anchor Y offset, as a percentage of the video.
280   */
281  viewportAnchorY = 100;
282  /**
283   * An enum representing how adding new cues will move existing cues.
284   */
285  scroll = "";
286}
287
288const COMMA$1 = ",", PERCENT_SIGN$1 = "%";
289function toNumber(text) {
290  const num = parseInt(text, 10);
291  return !Number.isNaN(num) ? num : null;
292}
293function toPercentage(text) {
294  const num = parseInt(text.replace(PERCENT_SIGN$1, ""), 10);
295  return !Number.isNaN(num) && num >= 0 && num <= 100 ? num : null;
296}
297function toCoords(text) {
298  if (!text.includes(COMMA$1))
299    return null;
300  const [x, y] = text.split(COMMA$1).map(toPercentage);
301  return x !== null && y !== null ? [x, y] : null;
302}
303function toFloat(text) {
304  const num = parseFloat(text);
305  return !Number.isNaN(num) ? num : null;
306}
307
308const HEADER_MAGIC = "WEBVTT", COMMA = ",", PERCENT_SIGN = "%", SETTING_SEP_RE = /[:=]/, SETTING_LINE_RE = /^[\s\t]*(region|vertical|line|position|size|align)[:=]/, NOTE_BLOCK_START = "NOTE", REGION_BLOCK_START = "REGION", REGION_BLOCK_START_RE = /^REGION:?[\s\t]+/, SPACE_RE = /[\s\t]+/, TIMESTAMP_SEP = "-->", TIMESTAMP_SEP_RE = /[\s\t]*-->[\s\t]+/, ALIGN_RE = /start|center|end|left|right/, LINE_ALIGN_RE = /start|center|end/, POS_ALIGN_RE = /line-(?:left|right)|center|auto/, TIMESTAMP_RE = /^(?:(\d{1,2}):)?(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/;
309var VTTBlock = /* @__PURE__ */ ((VTTBlock2) => {
310  VTTBlock2[VTTBlock2["None"] = 0] = "None";
311  VTTBlock2[VTTBlock2["Header"] = 1] = "Header";
312  VTTBlock2[VTTBlock2["Cue"] = 2] = "Cue";
313  VTTBlock2[VTTBlock2["Region"] = 3] = "Region";
314  VTTBlock2[VTTBlock2["Note"] = 4] = "Note";
315  return VTTBlock2;
316})(VTTBlock || {});
317class VTTParser {
318  f;
319  c = 0;
320  g = {};
321  h = {};
322  j = [];
323  a = null;
324  b = null;
325  k = [];
326  d;
327  l = "";
328  async init(init) {
329    this.f = init;
330    if (init.strict)
331      this.c = 1;
332    if (init.errors)
333      this.d = (await import('./errors.js')).ParseErrorBuilder;
334  }
335  parse(line, lineCount) {
336    if (line === "") {
337      if (this.a) {
338        this.j.push(this.a);
339        this.f.onCue?.(this.a);
340        this.a = null;
341      } else if (this.b) {
342        this.h[this.b.id] = this.b;
343        this.f.onRegion?.(this.b);
344        this.b = null;
345      } else if (this.c === 1) {
346        this.i(line, lineCount);
347        this.f.onHeaderMetadata?.(this.g);
348      }
349      this.c = 0;
350    } else if (this.c) {
351      switch (this.c) {
352        case 1:
353          this.i(line, lineCount);
354          break;
355        case 2:
356          if (this.a) {
357            const hasText = this.a.text.length > 0;
358            if (!hasText && SETTING_LINE_RE.test(line)) {
359              this.m(line.split(SPACE_RE), lineCount);
360            } else {
361              this.a.text += (hasText ? "\n" : "") + line;
362            }
363          }
364          break;
365        case 3:
366          this.n(line.split(SPACE_RE), lineCount);
367          break;
368      }
369    } else if (line.startsWith(NOTE_BLOCK_START)) {
370      this.c = 4;
371    } else if (line.startsWith(REGION_BLOCK_START)) {
372      this.c = 3;
373      this.b = new VTTRegion();
374      this.n(line.replace(REGION_BLOCK_START_RE, "").split(SPACE_RE), lineCount);
375    } else if (line.includes(TIMESTAMP_SEP)) {
376      const result = this.o(line, lineCount);
377      if (result) {
378        this.a = new VTTCue(result[0], result[1], "");
379        this.a.id = this.l;
380        this.m(result[2], lineCount);
381      }
382      this.c = 2;
383    } else if (lineCount === 1) {
384      this.i(line, lineCount);
385    }
386    this.l = line;
387  }
388  done() {
389    return {
390      metadata: this.g,
391      cues: this.j,
392      regions: Object.values(this.h),
393      errors: this.k
394    };
395  }
396  i(line, lineCount) {
397    if (lineCount > 1) {
398      if (SETTING_SEP_RE.test(line)) {
399        const [key, value] = line.split(SETTING_SEP_RE);
400        if (key)
401          this.g[key] = (value || "").replace(SPACE_RE, "");
402      }
403    } else if (line.startsWith(HEADER_MAGIC)) {
404      this.c = 1;
405    } else {
406      this.e(this.d?.p());
407    }
408  }
409  o(line, lineCount) {
410    const [startTimeText, trailingText = ""] = line.split(TIMESTAMP_SEP_RE), [endTimeText, ...settingsText] = trailingText.split(SPACE_RE), startTime = parseVTTTimestamp(startTimeText), endTime = parseVTTTimestamp(endTimeText);
411    if (startTime !== null && endTime !== null && endTime > startTime) {
412      return [startTime, endTime, settingsText];
413    } else {
414      if (startTime === null) {
415        this.e(this.d?.q(startTimeText, lineCount));
416      }
417      if (endTime === null) {
418        this.e(this.d?.r(endTimeText, lineCount));
419      }
420      if (startTime != null && endTime !== null && endTime > startTime) {
421        this.e(this.d?.s(startTime, endTime, lineCount));
422      }
423    }
424  }
425  /**
426   * @see {@link https://www.w3.org/TR/webvtt1/#region-settings-parsing}
427   */
428  n(settings, line) {
429    let badValue;
430    for (let i = 0; i < settings.length; i++) {
431      if (SETTING_SEP_RE.test(settings[i])) {
432        badValue = false;
433        const [name, value] = settings[i].split(SETTING_SEP_RE);
434        switch (name) {
435          case "id":
436            this.b.id = value;
437            break;
438          case "width":
439            const width = toPercentage(value);
440            if (width !== null)
441              this.b.width = width;
442            else
443              badValue = true;
444            break;
445          case "lines":
446            const lines = toNumber(value);
447            if (lines !== null)
448              this.b.lines = lines;
449            else
450              badValue = true;
451            break;
452          case "regionanchor":
453            const region = toCoords(value);
454            if (region !== null) {
455              this.b.regionAnchorX = region[0];
456              this.b.regionAnchorY = region[1];
457            } else
458              badValue = true;
459            break;
460          case "viewportanchor":
461            const viewport = toCoords(value);
462            if (viewport !== null) {
463              this.b.viewportAnchorX = viewport[0];
464              this.b.viewportAnchorY = viewport[1];
465            } else
466              badValue = true;
467            break;
468          case "scroll":
469            if (value === "up")
470              this.b.scroll = "up";
471            else
472              badValue = true;
473            break;
474          default:
475            this.e(this.d?.t(name, value, line));
476        }
477        if (badValue) {
478          this.e(this.d?.u(name, value, line));
479        }
480      }
481    }
482  }
483  /**
484   * @see {@link https://www.w3.org/TR/webvtt1/#cue-timings-and-settings-parsing}
485   */
486  m(settings, line) {
487    let badValue;
488    for (let i = 0; i < settings.length; i++) {
489      badValue = false;
490      if (SETTING_SEP_RE.test(settings[i])) {
491        const [name, value] = settings[i].split(SETTING_SEP_RE);
492        switch (name) {
493          case "region":
494            const region = this.h[value];
495            if (region)
496              this.a.region = region;
497            break;
498          case "vertical":
499            if (value === "lr" || value === "rl") {
500              this.a.vertical = value;
501              this.a.region = null;
502            } else
503              badValue = true;
504            break;
505          case "line":
506            const [linePos, lineAlign] = value.split(COMMA);
507            if (linePos.includes(PERCENT_SIGN)) {
508              const percentage = toPercentage(linePos);
509              if (percentage !== null) {
510                this.a.line = percentage;
511                this.a.snapToLines = false;
512              } else
513                badValue = true;
514            } else {
515              const number = toFloat(linePos);
516              if (number !== null)
517                this.a.line = number;
518              else
519                badValue = true;
520            }
521            if (LINE_ALIGN_RE.test(lineAlign)) {
522              this.a.lineAlign = lineAlign;
523            } else if (lineAlign) {
524              badValue = true;
525            }
526            if (this.a.line !== "auto")
527              this.a.region = null;
528            break;
529          case "position":
530            const [colPos, colAlign] = value.split(COMMA), position = toPercentage(colPos);
531            if (position !== null)
532              this.a.position = position;
533            else
534              badValue = true;
535            if (colAlign && POS_ALIGN_RE.test(colAlign)) {
536              this.a.positionAlign = colAlign;
537            } else if (colAlign) {
538              badValue = true;
539            }
540            break;
541          case "size":
542            const size = toPercentage(value);
543            if (size !== null) {
544              this.a.size = size;
545              if (size < 100)
546                this.a.region = null;
547            } else {
548              badValue = true;
549            }
550            break;
551          case "align":
552            if (ALIGN_RE.test(value)) {
553              this.a.align = value;
554            } else {
555              badValue = true;
556            }
557            break;
558          default:
559            this.e(this.d?.v(name, value, line));
560        }
561        if (badValue) {
562          this.e(this.d?.w(name, value, line));
563        }
564      }
565    }
566  }
567  e(error) {
568    if (!error)
569      return;
570    this.k.push(error);
571    if (this.f.strict) {
572      this.f.cancel();
573      throw error;
574    } else {
575      this.f.onError?.(error);
576    }
577  }
578}
579function parseVTTTimestamp(timestamp) {
580  const match = timestamp.match(TIMESTAMP_RE);
581  if (!match)
582    return null;
583  const hours = match[1] ? parseInt(match[1], 10) : 0, minutes = parseInt(match[2], 10), seconds = parseInt(match[3], 10), milliseconds = match[4] ? parseInt(match[4].padEnd(3, "0"), 10) : 0, total = hours * 3600 + minutes * 60 + seconds + milliseconds / 1e3;
584  if (hours < 0 || minutes < 0 || seconds < 0 || milliseconds < 0 || minutes > 59 || seconds > 59) {
585    return null;
586  }
587  return total;
588}
589function createVTTParser() {
590  return new VTTParser();
591}
592
593var vttParser = /*#__PURE__*/Object.freeze({
594  __proto__: null,
595  VTTBlock: VTTBlock,
596  VTTParser: VTTParser,
597  default: createVTTParser,
598  parseVTTTimestamp: parseVTTTimestamp
599});
600
601const DIGIT_RE = /[0-9]/, MULTI_SPACE_RE = /[\s\t]+/, TAG_NAME = {
602  c: "span",
603  i: "i",
604  b: "b",
605  u: "u",
606  ruby: "ruby",
607  rt: "rt",
608  v: "span",
609  lang: "span",
610  timestamp: "span"
611}, HTML_ENTITIES = {
612  "&amp;": "&",
613  "&lt;": "<",
614  "&gt;": ">",
615  "&quot;": '"',
616  "&#39;": "'",
617  "&nbsp;": "\xA0",
618  "&lrm;": "\u200E",
619  "&rlm;": "\u200F"
620}, HTML_ENTITY_RE = /&(?:amp|lt|gt|quot|#(0+)?39|nbsp|lrm|rlm);/g, COLORS = /* @__PURE__ */ new Set([
621  "white",
622  "lime",
623  "cyan",
624  "red",
625  "yellow",
626  "magenta",
627  "blue",
628  "black"
629]), BLOCK_TYPES = /* @__PURE__ */ new Set(Object.keys(TAG_NAME));
630function tokenizeVTTCue(cue) {
631  let buffer = "", mode = 1, result = [], stack = [], node;
632  for (let i = 0; i < cue.text.length; i++) {
633    const char = cue.text[i];
634    switch (mode) {
635      case 1:
636        if (char === "<") {
637          addText();
638          mode = 2;
639        } else {
640          buffer += char;
641        }
642        break;
643      case 2:
644        switch (char) {
645          case "\n":
646          case "	":
647          case " ":
648            addNode();
649            mode = 4;
650            break;
651          case ".":
652            addNode();
653            mode = 3;
654            break;
655          case "/":
656            mode = 5;
657            break;
658          case ">":
659            addNode();
660            mode = 1;
661            break;
662          default:
663            if (!buffer && DIGIT_RE.test(char))
664              mode = 6;
665            buffer += char;
666            break;
667        }
668        break;
669      case 3:
670        switch (char) {
671          case "	":
672          case " ":
673          case "\n":
674            addClass();
675            if (node)
676              node.class?.trim();
677            mode = 4;
678            break;
679          case ".":
680            addClass();
681            break;
682          case ">":
683            addClass();
684            if (node)
685              node.class?.trim();
686            mode = 1;
687            break;
688          default:
689            buffer += char;
690        }
691        break;
692      case 4:
693        if (char === ">") {
694          buffer = buffer.replace(MULTI_SPACE_RE, " ");
695          if (node?.type === "v")
696            node.voice = replaceHTMLEntities(buffer);
697          else if (node?.type === "lang")
698            node.lang = replaceHTMLEntities(buffer);
699          buffer = "";
700          mode = 1;
701        } else {
702          buffer += char;
703        }
704        break;
705      case 5:
706        if (char === ">") {
707          buffer = "";
708          node = stack.pop();
709          mode = 1;
710        }
711        break;
712      case 6:
713        if (char === ">") {
714          const time = parseVTTTimestamp(buffer);
715          if (time !== null && time >= cue.startTime && time <= cue.endTime) {
716            buffer = "timestamp";
717            addNode();
718            node.time = time;
719          }
720          buffer = "";
721          mode = 1;
722        } else {
723          buffer += char;
724        }
725        break;
726    }
727  }
728  function addNode() {
729    if (BLOCK_TYPES.has(buffer)) {
730      const parent = node;
731      node = createBlockNode(buffer);
732      if (parent) {
733        if (stack[stack.length - 1] !== parent)
734          stack.push(parent);
735        parent.children.push(node);
736      } else
737        result.push(node);
738    }
739    buffer = "";
740    mode = 1;
741  }
742  function addClass() {
743    if (node && buffer) {
744      const color = buffer.replace("bg_", "");
745      if (COLORS.has(color)) {
746        node[buffer.startsWith("bg_") ? "bgColor" : "color"] = color;
747      } else {
748        node.class = !node.class ? buffer : node.class + " " + buffer;
749      }
750    }
751    buffer = "";
752  }
753  function addText() {
754    if (!buffer)
755      return;
756    const text = { type: "text", data: replaceHTMLEntities(buffer) };
757    node ? node.children.push(text) : result.push(text);
758    buffer = "";
759  }
760  if (mode === 1)
761    addText();
762  return result;
763}
764function createBlockNode(type) {
765  return {
766    tagName: TAG_NAME[type],
767    type,
768    children: []
769  };
770}
771function replaceHTMLEntities(text) {
772  return text.replace(HTML_ENTITY_RE, (entity) => HTML_ENTITIES[entity] || "'");
773}
774
775function setCSSVar(el, name, value) {
776  el.style.setProperty(`--${name}`, value + "");
777}
778function setDataAttr(el, name, value = true) {
779  el.setAttribute(`data-${name}`, value === true ? "" : value + "");
780}
781function setPartAttr(el, name) {
782  el.setAttribute("
782data-part", name);
783}
784function getLineHeight(el) {
785  return parseFloat(getComputedStyle(el).lineHeight) || 0;
786}
787
788function createVTTCueTemplate(cue) {
789  if (IS_SERVER) {
790    throw Error(
791      "[media-captions] called `createVTTCueTemplate` on the server - use `renderVTTCueString`"
792    );
793  }
794  const template = document.createElement("template");
795  template.innerHTML = renderVTTCueString(cue);
796  return { cue, content: template.content };
797}
798function renderVTTCueString(cue, currentTime = 0) {
799  return renderVTTTokensString(tokenizeVTTCue(cue), currentTime);
800}
801function renderVTTTokensString(tokens, currentTime = 0) {
802  let attrs, result = "";
803  for (const token of tokens) {
804    if (token.type === "text") {
805      result += token.data;
806    } else {
807      const isTimestamp = token.type === "timestamp";
808      attrs = {};
809      attrs.class = token.class;
810      attrs.title = token.type === "v" && token.voice;
811      attrs.lang = token.type === "lang" && token.lang;
812      attrs["data-part"] = token.type === "v" && "voice";
813      if (isTimestamp) {
814        attrs["data-part"] = "timed";
815        attrs["data-time"] = token.time;
816        attrs["data-future"] = token.time > currentTime;
817        attrs["data-past"] = token.time < currentTime;
818      }
819      attrs.style = `${token.color ? `color: ${token.color};` : ""}${token.bgColor ? `background-color: ${token.bgColor};` : ""}`;
820      const attributes = Object.entries(attrs).filter((v) => v[1]).map((v) => `${v[0]}="${v[1] === true ? "" : v[1]}"`).join(" ");
821      result += `<${token.tagName}${attributes ? " " + attributes : ""}>${renderVTTTokensString(
822        token.children
823      )}</${token.tagName}>`;
824    }
825  }
826  return result;
827}
828function updateTimedVTTCueNodes(root, currentTime) {
829  if (IS_SERVER)
830    return;
831  for (const el of root.querySelectorAll('[data-
vendor: 7,564 bytes, lines 831-1090
831part="timed"]')) {
832    const time = Number(el.getAttribute("data-time"));
833    if (Number.isNaN(time))
834      continue;
835    if (time > currentTime)
836      setDataAttr(el, "future");
837    else
838      el.removeAttribute("data-future");
839    if (time < currentTime)
840      setDataAttr(el, "past");
841    else
842      el.removeAttribute("data-past");
843  }
844}
845
846function debounce(fn, delay) {
847  let timeout = null, args;
848  function run() {
849    clear();
850    fn(...args);
851    args = void 0;
852  }
853  function clear() {
854    clearTimeout(timeout);
855    timeout = null;
856  }
857  function debounce2() {
858    args = [].slice.call(arguments);
859    clear();
860    timeout = setTimeout(run, delay);
861  }
862  return debounce2;
863}
864
865const STARTING_BOX = Symbol(0);
866function createBox(box) {
867  if (box instanceof HTMLElement) {
868    return {
869      top: box.offsetTop,
870      width: box.clientWidth,
871      height: box.clientHeight,
872      left: box.offsetLeft,
873      right: box.offsetLeft + box.clientWidth,
874      bottom: box.offsetTop + box.clientHeight
875    };
876  }
877  return { ...box };
878}
879function moveBox(box, axis, delta) {
880  switch (axis) {
881    case "+x":
882      box.left += delta;
883      box.right += delta;
884      break;
885    case "-x":
886      box.left -= delta;
887      box.right -= delta;
888      break;
889    case "+y":
890      box.top += delta;
891      box.bottom += delta;
892      break;
893    case "-y":
894      box.top -= delta;
895      box.bottom -= delta;
896      break;
897  }
898}
899function isBoxCollision(a, b) {
900  return a.left <= b.right && a.right >= b.left && a.top <= b.bottom && a.bottom >= b.top;
901}
902function isAnyBoxCollision(box, boxes) {
903  for (let i = 0; i < boxes.length; i++)
904    if (isBoxCollision(box, boxes[i]))
905      return boxes[i];
906  return null;
907}
908function isWithinBox(container, box) {
909  return box.top >= 0 && box.bottom <= container.height && box.left >= 0 && box.right <= container.width;
910}
911function isBoxOutOfBounds(container, box, axis) {
912  switch (axis) {
913    case "+x":
914      return box.left < 0;
915    case "-x":
916      return box.right > container.width;
917    case "+y":
918      return box.top < 0;
919    case "-y":
920      return box.bottom > container.height;
921  }
922}
923function calcBoxIntersectPercentage(container, box) {
924  const x = Math.max(0, Math.min(container.width, box.right) - Math.max(0, box.left)), y = Math.max(0, Math.min(container.height, box.bottom) - Math.max(0, box.top)), intersectArea = x * y;
925  return intersectArea / (container.height * container.width);
926}
927function createCSSBox(container, box) {
928  return {
929    top: box.top / container.height,
930    left: box.left / container.width,
931    right: (container.width - box.right) / container.width,
932    bottom: (container.height - box.bottom) / container.height
933  };
934}
935function resolveRelativeBox(container, box) {
936  box.top = box.top * container.height;
937  box.left = box.left * container.width;
938  box.right = container.width - box.right * container.width;
939  box.bottom = container.height - box.bottom * container.height;
940  return box;
941}
942const BOX_SIDES = ["top", "left", "right", "bottom"];
943function setBoxCSSVars(el, container, box, prefix) {
944  const cssBox = createCSSBox(container, box);
945  for (const side of BOX_SIDES) {
946    setCSSVar(el, `${prefix}-${side}`, cssBox[side] * 100 + "%");
947  }
948}
949function avoidBoxCollisions(container, box, boxes, axis) {
950  let percentage = 1, positionedBox, startBox = { ...box };
951  for (let i = 0; i < axis.length; i++) {
952    while (isBoxOutOfBounds(container, box, axis[i]) || isWithinBox(container, box) && isAnyBoxCollision(box, boxes)) {
953      moveBox(box, axis[i], 1);
954    }
955    if (isWithinBox(container, box))
956      return box;
957    const intersection = calcBoxIntersectPercentage(container, box);
958    if (percentage > intersection) {
959      positionedBox = { ...box };
960      percentage = intersection;
961    }
962    box = { ...startBox };
963  }
964  return positionedBox || startBox;
965}
966
967const POSITION_OVERRIDE = Symbol(0);
968function positionCue(container, cue, displayEl, boxes) {
969  let cueEl = displayEl.firstElementChild, line = computeCueLine(cue), displayBox, axis = [];
970  if (!displayEl[STARTING_BOX]) {
971    displayEl[STARTING_BOX] = createStartingBox(container, displayEl);
972  }
973  displayBox = resolveRelativeBox(container, { ...displayEl[STARTING_BOX] });
974  if (displayEl[POSITION_OVERRIDE]) {
975    axis = [displayEl[POSITION_OVERRIDE] === "top" ? "+y" : "-y", "+x", "-x"];
976  } else if (cue.snapToLines) {
977    let size;
978    switch (cue.vertical) {
979      case "":
980        axis = ["+y", "-y"];
981        size = "height";
982        break;
983      case "rl":
984        axis = ["+x", "-x"];
985        size = "width";
986        break;
987      case "lr":
988        axis = ["-x", "+x"];
989        size = "width";
990        break;
991    }
992    let step = getLineHeight(cueEl), position = step * Math.round(line), maxPosition = container[size] + step, initialAxis = axis[0];
993    if (Math.abs(position) > maxPosition) {
994      position = position < 0 ? -1 : 1;
995      position *= Math.ceil(maxPosition / step) * step;
996    }
997    if (line < 0) {
998      position += cue.vertical === "" ? container.height : container.width;
999      axis = axis.reverse();
1000    }
1001    moveBox(displayBox, initialAxis, position);
1002  } else {
1003    const isHorizontal = cue.vertical === "", posAxis = isHorizontal ? "+y" : "+x", size = isHorizontal ? displayBox.height : displayBox.width;
1004    moveBox(
1005      displayBox,
1006      posAxis,
1007      (isHorizontal ? container.height : container.width) * line / 100
1008    );
1009    moveBox(
1010      displayBox,
1011      posAxis,
1012      cue.lineAlign === "center" ? size / 2 : cue.lineAlign === "end" ? size : 0
1013    );
1014    axis = isHorizontal ? ["-y", "+y", "-x", "+x"] : ["-x", "+x", "-y", "+y"];
1015  }
1016  displayBox = avoidBoxCollisions(container, displayBox, boxes, axis);
1017  setBoxCSSVars(displayEl, container, displayBox, "cue");
1018  return displayBox;
1019}
1020function createStartingBox(container, cueEl) {
1021  const box = createBox(cueEl), pos = getStyledPositions(cueEl);
1022  cueEl[POSITION_OVERRIDE] = false;
1023  if (pos.top) {
1024    box.top = pos.top;
1025    box.bottom = pos.top + box.height;
1026    cueEl[POSITION_OVERRIDE] = "top";
1027  }
1028  if (pos.bottom) {
1029    const bottom = container.height - pos.bottom;
1030    box.top = bottom - box.height;
1031    box.bottom = bottom;
1032    cueEl[POSITION_OVERRIDE] = "bottom";
1033  }
1034  if (pos.left)
1035    box.left = pos.left;
1036  if (pos.right)
1037    box.right = container.width - pos.right;
1038  return createCSSBox(container, box);
1039}
1040function getStyledPositions(el) {
1041  const positions = {};
1042  for (const side of BOX_SIDES) {
1043    positions[side] = parseFloat(el.style.getPropertyValue(`--cue-${side}`));
1044  }
1045  return positions;
1046}
1047function computeCueLine(cue) {
1048  if (cue.line === "auto") {
1049    if (!cue.snapToLines) {
1050      return 100;
1051    } else {
1052      return -1;
1053    }
1054  }
1055  return cue.line;
1056}
1057function computeCuePosition(cue) {
1058  if (cue.position === "auto") {
1059    switch (cue.align) {
1060      case "start":
1061      case "left":
1062        return 0;
1063      case "right":
1064      case "end":
1065        return 100;
1066      default:
1067        return 50;
1068    }
1069  }
1070  return cue.position;
1071}
1072function computeCuePositionAlignment(cue, dir) {
1073  if (cue.positionAlign === "auto") {
1074    switch (cue.align) {
1075      case "start":
1076        return dir === "ltr" ? "line-left" : "line-right";
1077      case "end":
1078        return dir === "ltr" ? "line-right" : "line-left";
1079      case "center":
1080        return "center";
1081      default:
1082        return `line-${cue.align}`;
1083    }
1084  }
1085  return cue.positionAlign;
1086}
1087
1088const REGION_AXIS = ["-y", "+y", "-x", "+x"];
1089function positionRegion(container, region, regionEl, boxes) {
1090  let cues = Array.from(regionEl.querySelectorAll('[
1090data-
vendor: 7,440 bytes, lines 1090-1324
1090part="cue-display"]')), height = 0, limit = Math.max(0, cues.length - region.lines);
1091  for (let i = cues.length - 1; i >= limit; i--) {
1092    height += cues[i].offsetHeight;
1093  }
1094  setCSSVar(regionEl, "region-height", height + "px");
1095  if (!regionEl[STARTING_BOX]) {
1096    regionEl[STARTING_BOX] = createCSSBox(container, createBox(regionEl));
1097  }
1098  let box = { ...regionEl[STARTING_BOX] };
1099  box = resolveRelativeBox(container, box);
1100  box.width = regionEl.clientWidth;
1101  box.height = height;
1102  box.right = box.left + box.width;
1103  box.bottom = box.top + height;
1104  box = avoidBoxCollisions(container, box, boxes, REGION_AXIS);
1105  setBoxCSSVars(regionEl, container, box, "region");
1106  return box;
1107}
1108
1109class CaptionsRenderer {
1110  overlay;
1111  z;
1112  A = 0;
1113  C = "ltr";
1114  B = [];
1115  D = false;
1116  E;
1117  h = /* @__PURE__ */ new Map();
1118  j = /* @__PURE__ */ new Map();
1119  /* Text direction. */
1120  get dir() {
1121    return this.C;
1122  }
1123  set dir(dir) {
1124    this.C = dir;
1125    setDataAttr(this.overlay, "dir", dir);
1126  }
1127  get currentTime() {
1128    return this.A;
1129  }
1130  set currentTime(time) {
1131    this.A = time;
1132    this.update();
1133  }
1134  constructor(overlay, init) {
1135    this.overlay = overlay;
1136    this.dir = init?.dir ?? "ltr";
1137    overlay.setAttribute("translate", "yes");
1138    overlay.setAttribute("aria-live", "off");
1139    overlay.setAttribute("aria-atomic", "true");
1140    setPartAttr(overlay, "captions");
1141    this.G();
1142    this.E = new ResizeObserver(this.I.bind(this));
1143    this.E.observe(overlay);
1144  }
1145  changeTrack({ regions, cues }) {
1146    this.reset();
1147    this.J(regions);
1148    for (const cue of cues)
1149      this.j.set(cue, null);
1150    this.update();
1151  }
1152  addCue(cue) {
1153    this.j.set(cue, null);
1154    this.update();
1155  }
1156  removeCue(cue) {
1157    this.j.delete(cue);
1158    this.update();
1159  }
1160  update(forceUpdate = false) {
1161    this.H(forceUpdate);
1162  }
1163  reset() {
1164    this.j.clear();
1165    this.h.clear();
1166    this.B = [];
1167    this.overlay.textContent = "";
1168  }
1169  destroy() {
1170    this.reset();
1171    this.E.disconnect();
1172  }
1173  I() {
1174    this.D = true;
1175    this.K();
1176  }
1177  K = debounce(() => {
1178    this.D = false;
1179    this.G();
1180    for (const el of this.h.values()) {
1181      el[STARTING_BOX] = null;
1182    }
1183    for (const el of this.j.values()) {
1184      if (el)
1185        el[STARTING_BOX] = null;
1186    }
1187    this.H(true);
1188  }, 50);
1189  G() {
1190    this.z = createBox(this.overlay);
1191    setCSSVar(this.overlay, "overlay-width", this.z.width + "px");
1192    setCSSVar(this.overlay, "overlay-height", this.z.height + "px");
1193  }
1194  H(forceUpdate = false) {
1195    if (!this.j.size || this.D)
1196      return;
1197    let cue, activeCues = [...this.j.keys()].filter((cue2) => this.A >= cue2.startTime && this.A <= cue2.endTime).sort(
1198      (cueA, cueB) => cueA.startTime !== cueB.startTime ? cueA.startTime - cueB.startTime : cueA.endTime - cueB.endTime
1199    ), activeRegions = activeCues.map((cue2) => cue2.region);
1200    for (let i = 0; i < this.B.length; i++) {
1201      cue = this.B[i];
1202      if (activeCues[i] === cue)
1203        continue;
1204      if (cue.region && !activeRegions.includes(cue.region)) {
1205        const regionEl = this.h.get(cue.region.id);
1206        if (regionEl) {
1207          regionEl.removeAttribute("data-active");
1208          forceUpdate = true;
1209        }
1210      }
1211      const cueEl = this.j.get(cue);
1212      if (cueEl) {
1213        cueEl.remove();
1214        forceUpdate = true;
1215      }
1216    }
1217    for (let i = 0; i < activeCues.length; i++) {
1218      cue = activeCues[i];
1219      let cueEl = this.j.get(cue);
1220      if (!cueEl)
1221        this.j.set(cue, cueEl = this.L(cue));
1222      const regionEl = this.F(cue) && this.h.get(cue.region.id);
1223      if (regionEl && !regionEl.hasAttribute("data-active")) {
1224        requestAnimationFrame(() => setDataAttr(regionEl, "active"));
1225        forceUpdate = true;
1226      }
1227      if (!cueEl.isConnected) {
1228        (regionEl || this.overlay).append(cueEl);
1229        forceUpdate = true;
1230      }
1231    }
1232    if (forceUpdate) {
1233      const boxes = [], seen = /* @__PURE__ */ new Set();
1234      for (let i = activeCues.length - 1; i >= 0; i--) {
1235        cue = activeCues[i];
1236        if (seen.has(cue.region || cue))
1237          continue;
1238        const isRegion = this.F(cue), el = isRegion ? this.h.get(cue.region.id) : this.j.get(cue);
1239        if (isRegion) {
1240          boxes.push(positionRegion(this.z, cue.region, el, boxes));
1241        } else {
1242          boxes.push(positionCue(this.z, cue, el, boxes));
1243        }
1244        seen.add(isRegion ? cue.region : cue);
1245      }
1246    }
1247    updateTimedVTTCueNodes(this.overlay, this.A);
1248    this.B = activeCues;
1249  }
1250  J(regions) {
1251    if (!regions)
1252      return;
1253    for (const region of regions) {
1254      const el = this.M(region);
1255      this.h.set(region.id, el);
1256      this.overlay.append(el);
1257    }
1258  }
1259  M(region) {
1260    const el = document.createElement("div");
1261    setPartAttr(el, "region");
1262    setDataAttr(el, "id", region.id);
1263    setDataAttr(el, "scroll", region.scroll);
1264    setCSSVar(el, "region-width", region.width + "%");
1265    setCSSVar(el, "region-anchor-x", region.regionAnchorX);
1266    setCSSVar(el, "region-anchor-y", region.regionAnchorY);
1267    setCSSVar(el, "region-viewport-anchor-x", region.viewportAnchorX);
1268    setCSSVar(el, "region-viewport-anchor-y", region.viewportAnchorY);
1269    setCSSVar(el, "region-lines", region.lines);
1270    return el;
1271  }
1272  L(cue) {
1273    const display = document.createElement("div"), position = computeCuePosition(cue), positionAlignment = computeCuePositionAlignment(cue, this.C);
1274    setPartAttr(display, "cue-display");
1275    if (cue.vertical !== "")
1276      setDataAttr(display, "vertical");
1277    setCSSVar(display, "cue-text-align", cue.align);
1278    if (cue.style) {
1279      for (const prop of Object.keys(cue.style)) {
1280        display.style.setProperty(prop, cue.style[prop]);
1281      }
1282    }
1283    if (!this.F(cue)) {
1284      setCSSVar(
1285        display,
1286        "cue-writing-mode",
1287        cue.vertical === "" ? "horizontal-tb" : cue.vertical === "lr" ? "vertical-lr" : "vertical-rl"
1288      );
1289      if (!cue.style?.["--cue-width"]) {
1290        let maxSize = position;
1291        if (positionAlignment === "line-left") {
1292          maxSize = 100 - position;
1293        } else if (positionAlignment === "center" && position <= 50) {
1294          maxSize = position * 2;
1295        } else if (positionAlignment === "center" && position > 50) {
1296          maxSize = (100 - position) * 2;
1297        }
1298        const size = cue.size < maxSize ? cue.size : maxSize;
1299        if (cue.vertical === "")
1300          setCSSVar(display, "cue-width", size + "%");
1301        else
1302          setCSSVar(display, "cue-height", size + "%");
1303      }
1304    } else {
1305      setCSSVar(
1306        display,
1307        "cue-offset",
1308        `${position - (positionAlignment === "line-right" ? 100 : positionAlignment === "center" ? 50 : 0)}%`
1309      );
1310    }
1311    const el = document.createElement("div");
1312    setPartAttr(el, "cue");
1313    if (cue.id)
1314      setDataAttr(el, "id", cue.id);
1315    el.innerHTML = renderVTTCueString(cue);
1316    display.append(el);
1317    return display;
1318  }
1319  F(cue) {
1320    return cue.region && cue.size === 100 && cue.vertical === "" && cue.line === "auto";
1321  }
1322}
1323
1324export { CaptionsRenderer as C, ParseError as P, TextCue as T, VTTParser as V, VTTBlock as a, VTTCue as b, ParseErrorCode as c, parseResponse as d, parseByteStream as e, parseText as f, parseTextStream as g, VTTRegion as h, createVTTCueTemplate as i, renderVTTTokensString as j, parseVTTTimestamp as p, renderVTTCueString as r, tokenizeVTTCue as t, updateTimedVTTCueNodes as u };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.