├── .github └── workflows │ ├── codeql-analysis.yml │ ├── publish.yml │ └── release.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── SECURITY.md ├── assets ├── pexels-cottonbro-5532773.mp4 ├── subtitle.srt └── subtitle.vtt ├── browser.js ├── bun.lockb ├── dist ├── main.es.js ├── main.iife.js └── source.es.js ├── index.html ├── jsr.json ├── main.d.ts ├── main.js ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── src ├── cue.d.ts ├── cue.js ├── helpers.d.ts ├── helpers.js ├── track.d.ts ├── track.js ├── transformer.d.ts └── transformer.js ├── tsconfig.json ├── vite.config.esm.js ├── vite.config.iife.js └── vite.config.js /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '18 11 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "Automatic Releaser" 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v2.*' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | publish: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | id-token: write 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | 21 | - name: Publish to NPM 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: '18' 25 | registry-url: 'https://registry.npmjs.org' 26 | - run: npm install 27 | - run: npm ci 28 | - run: npm run build 29 | - run: npm publish 30 | env: 31 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 32 | - name: Publish to JSR 33 | uses: actions/checkout@v4 34 | - run: npx jsr publish -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Releases 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v2.*' 7 | 8 | jobs: 9 | 10 | build: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: ncipollo/release-action@v1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist-ssr 12 | *.local 13 | 14 | # Editor directories and files 15 | .vscode/* 16 | !.vscode/extensions.json 17 | .idea 18 | .DS_Store 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github 2 | .idea 3 | 4 | assets/* 5 | node_modules/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Code IT 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 💐 Add support for SRT subtitles in HTML5 video elements 2 | 3 | > ✅ This package uses **0** external dependencies! 4 | 5 | Officially only VTT files are supported by the HTML5 track element. 6 | This package will convert your SRT subtitles on the fly to VTT subtitles. 7 | 8 | ### Installation 9 | 10 | As a NPM package, works both in the browser and NodeJS 11 | 12 | ```text 13 | npm install srt-support-for-html5-videos 14 | ``` 15 | 16 | **CDN** 17 | - Ready to use script, just include it, and it will parse all video elements to convert the tracks 18 | ```text 19 | https://cdn.jsdelivr.net/npm/srt-support-for-html5-videos/dist/main.iife.js 20 | ``` 21 | 22 | **ES Module** 23 | - Use as ES Module, see usage section 24 | ```text 25 | https://cdn.jsdelivr.net/npm/srt-support-for-html5-videos/dist/main.es.js 26 | ``` 27 | 28 | ### Usage 29 | If you installed it as a package using NPM or as an ES Module using the CDN, you have to call the `transformSrtTracks()` manually in order to transform the tracks. 30 | 31 | ```javascript 32 | // If using NPM 33 | import { transformSrtTracks } from 'srt-support-for-html5-videos'; 34 | // If using CDN 35 | import { transformSrtTracks } from 'https://cdn.jsdelivr.net/npm/srt-support-for-html5-videos/dist/main.es.js'; 36 | 37 | // Single video element 38 | const video = document.getElementById('video'); 39 | 40 | transformSrtTracks(video); 41 | 42 | // All video elements 43 | const videos = document.querySelectorAll('video'); 44 | 45 | [...videos].forEach(transformSrtTracks); 46 | ``` 47 | 48 | If your SRT file is encoded in a different format than *UTF-8* you must specify the encoding format in the `track` element using the `data-encoding` *attribute*. 49 | 50 | ```html 51 | 55 | ``` 56 | 57 | ### Other functions 58 | Some more functions are exported, these are just helper functions, you can import and use them if you have any use for them. 59 | 60 | #### toVttCue 61 | Function is internally used to covert a srt cue into a WebVTT compatible cue. 62 | 63 | ```javascript 64 | /** 65 | * Converts a SRT cue into a VTT compatible cue 66 | * 67 | * For example 68 | * 69 | * 1 70 | * 00:00:00,498 --> 00:00:02,827 71 | * Here's what I love most 72 | * about food and diet. 73 | * 74 | * Will be converted into 75 | * 76 | * Cue { 77 | * number: 1, 78 | * startTime: 0.498 79 | * endTime: 2.827, 80 | * text: 'Here\'s what I love most\nabout food and diet.' 81 | * } 82 | * 83 | */ 84 | import { toVttCue } from 'srt-support-for-html5-videos'; 85 | ``` 86 | #### hmsToSeconds 87 | Converts a `HH:MM:SS.MS` string into a *number in seconds* 88 | 89 | ```javascript 90 | /** 91 | * Converts a VTT or SRT timing `string` 92 | * to a `number` in seconds + milliseconds 93 | */ 94 | import { hmsToSeconds } from 'srt-support-for-html5-videos'; 95 | 96 | const seconds = hmsToSeconds('00:00:02.827'); // 2.827 97 | ``` 98 | #### fetchTrack 99 | Fetches the contents of a track and returns the body. 100 | 101 | ```javascript 102 | /** 103 | * Fetches the contents of a track source 104 | */ 105 | import { fetchTrack } from 'srt-support-for-html5-videos'; 106 | 107 | const content = await fetchTrack('https://example.com/path/my-subtitle.srt'); 108 | ``` 109 | 110 | #### srt2vtt 111 | Convert SRT to VTT. 112 | 113 | There is no advanced API returning to add extra *VTT* sections like a header, comment or styles. 114 | 115 | ```javascript 116 | /** 117 | * Converts SRT formatted string into a WebVTT formated string 118 | */ 119 | import { srt2vtt } from 'srt-support-for-html5-videos'; 120 | 121 | const vtt = srt2vtt(srt); 122 | ``` 123 | 124 | ### Support me 125 | [](https://www.buymeacoffee.com/codeit) -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 2.x.x | :white_check_mark: | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | You can report security issues to richard@codeit.ninja 12 | -------------------------------------------------------------------------------- /assets/pexels-cottonbro-5532773.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeit-ninja/SRT-Support-for-HTML5-videos/0e27155e8ecfff117a9ccea126b32ade369d7136/assets/pexels-cottonbro-5532773.mp4 -------------------------------------------------------------------------------- /assets/subtitle.srt: -------------------------------------------------------------------------------- 1 | 1 2 | 00:00:00,498 --> 00:00:02,827 3 | - Here's what I love most 4 | about food and diet. 5 | 6 | 2 7 | 00:00:02,827 --> 00:00:06,383 8 | We all eat several times a day, 9 | and we're totally in charge 10 | 11 | 3 12 | 00:00:06,383 --> 00:00:09,427 13 | of what goes on our plate 14 | and what stays off. 15 | 16 | 4 17 | 00:00:10,144 --> 00:00:13,000 18 | This was a demo showing that we successfully 19 | converted srt into WebVTT compatible subtitles 20 | 21 | -------------------------------------------------------------------------------- /assets/subtitle.vtt: -------------------------------------------------------------------------------- 1 | WEBVTT 2 | 00:00:00.500 --> 00:00:02.000 3 | The Web is always changing 4 | 5 | 00:00:02.500 --> 00:00:04.300 6 | and the way we access it is changing 7 | 8 | 4 9 | 00:00:05.144 --> 00:00:13.000 10 | This is a demo WebVTT file -------------------------------------------------------------------------------- /browser.js: -------------------------------------------------------------------------------- 1 | import { transformSrtTracks } from './src/transformer.js'; 2 | 3 | document.addEventListener('DOMContentLoaded', () => [...document.querySelectorAll('video')].forEach(transformSrtTracks)); -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeit-ninja/SRT-Support-for-HTML5-videos/0e27155e8ecfff117a9ccea126b32ade369d7136/bun.lockb -------------------------------------------------------------------------------- /dist/main.es.js: -------------------------------------------------------------------------------- 1 | var c = Object.defineProperty; 2 | var o = (n, t, e) => t in n ? c(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e; 3 | var s = (n, t, e) => (o(n, typeof t != "symbol" ? t + "" : t, e), e); 4 | class l { 5 | /** 6 | * 7 | * @param {number} number 8 | * @param {number} startTime 9 | * @param {number} endTime 10 | * @param {string} text 11 | */ 12 | constructor(t, e, r, i) { 13 | /** 14 | * @readonly 15 | * @type {number} 16 | */ 17 | s(this, "number"); 18 | /** 19 | * @readonly 20 | * @type {number} 21 | */ 22 | s(this, "startTime"); 23 | /** 24 | * @readonly 25 | * @type {number} 26 | */ 27 | s(this, "endTime"); 28 | /** 29 | * @readonly 30 | * @type {string} 31 | */ 32 | s(this, "text"); 33 | this.number = t, this.startTime = e, this.endTime = r, this.text = i; 34 | } 35 | } 36 | function d(n) { 37 | try { 38 | if (!n || n === " ") 39 | return !1; 40 | const t = { 41 | number: parseInt(n.match(/^\d+/g)[0]), 42 | timing: { 43 | start: n.match(/(\d+:){2}\d+,\d+/g)[0].replace(",", "."), 44 | end: n.match(/(\d+:){2}\d+,\d+/g)[1].replace(",", ".") 45 | }, 46 | text: n.split(/\r?\n/g).slice(2, n.split(/\r?\n/g).length).join(` 47 | `) 48 | }; 49 | return new l(t.number, a(t.timing.start), a(t.timing.end), t.text); 50 | } catch { 51 | return !1; 52 | } 53 | } 54 | function a(n) { 55 | let t = n.split(":"), e = 0, r = 1; 56 | for (; t.length > 0; ) 57 | e += r * parseFloat(t.pop(), 10), r *= 60; 58 | return e; 59 | } 60 | async function h(n, t = "utf-8") { 61 | return (!t || t === "") && (t = "utf-8"), fetch(n).then((e) => e.arrayBuffer()).then((e) => new TextDecoder(t).decode(e)); 62 | } 63 | function u(n) { 64 | return `WEBVTT 65 | 66 | ` + n.split(/\n/g).map((t) => t.replace(/((\d+:){0,2}\d+),(\d+)/g, "$1.$3")).join(` 67 | `); 68 | } 69 | class m { 70 | /** 71 | * Parses a `HTMLTrackElement` 72 | * 73 | * @param {HTMLTrackElement} track 74 | */ 75 | constructor(t) { 76 | /** 77 | * @readonly 78 | * @type {HTMLTrackElement} 79 | */ 80 | s(this, "element"); 81 | /** 82 | * @readonly 83 | * @type {string} 84 | */ 85 | s(this, "src"); 86 | /** 87 | * @readonly 88 | * @type {string} 89 | */ 90 | s(this, "encoding"); 91 | /** 92 | * @readonly 93 | * @type {string} 94 | */ 95 | s(this, "lang"); 96 | /** 97 | * @readonly 98 | * @type {string} 99 | */ 100 | s(this, "kind"); 101 | /** 102 | * @readonly 103 | * @type {string} 104 | */ 105 | s(this, "label"); 106 | /** 107 | * @readonly 108 | * @type {boolean} 109 | */ 110 | s(this, "default"); 111 | /** 112 | * @readonly 113 | * @type {string} 114 | */ 115 | s(this, "body"); 116 | /** 117 | * @readonly 118 | * @type {boolean} 119 | */ 120 | s(this, "needsTransform"); 121 | /** 122 | * @readonly 123 | * @type {Cue[]} 124 | */ 125 | s(this, "cues", []); 126 | this.element = t, this.src = t.src, this.encoding = t.dataset.encoding, this.lang = t.srclang, this.kind = t.kind, this.label = t.label, this.default = t.default, this.needsTransform = !this.src.toLowerCase().endsWith(".vtt"); 127 | } 128 | async parse() { 129 | this.body = await h(this.src, this.encoding), this.cues = this.body.split(/\r?\n\r?\n/g).map(d).filter(Boolean); 130 | } 131 | } 132 | async function T(n) { 133 | const t = [...n.querySelectorAll("track")].map((e) => new m(e)); 134 | for (const e of t) { 135 | if (!e.needsTransform) 136 | continue; 137 | await e.parse(), e.element.remove(); 138 | const r = n.addTextTrack(e.kind, e.label, e.lang); 139 | e.cues.forEach((i) => r.addCue(new VTTCue(i.startTime, i.endTime, i.text))), e.default && (r.mode = "showing"); 140 | } 141 | } 142 | export { 143 | h as fetchTrack, 144 | a as hmsToSeconds, 145 | u as srt2vtt, 146 | d as toVttCue, 147 | T as transformSrtTracks 148 | }; 149 | -------------------------------------------------------------------------------- /dist/main.iife.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";class a{number;startTime;endTime;text;constructor(e,t,s,r){this.number=e,this.startTime=t,this.endTime=s,this.text=r}}function c(n){try{if(!n||n===" ")return!1;const e={number:parseInt(n.match(/^\d+/g)[0]),timing:{start:n.match(/(\d+:){2}\d+,\d+/g)[0].replace(",","."),end:n.match(/(\d+:){2}\d+,\d+/g)[1].replace(",",".")},text:n.split(/\r?\n/g).slice(2,n.split(/\r?\n/g).length).join(` 2 | `)};return new a(e.number,i(e.timing.start),i(e.timing.end),e.text)}catch{return!1}}function i(n){let e=n.split(":"),t=0,s=1;for(;e.length>0;)t+=s*parseFloat(e.pop(),10),s*=60;return t}async function o(n,e="utf-8"){return(!e||e==="")&&(e="utf-8"),fetch(n).then(t=>t.arrayBuffer()).then(t=>new TextDecoder(e).decode(t))}class d{element;src;encoding;lang;kind;label;default;body;needsTransform;cues=[];constructor(e){this.element=e,this.src=e.src,this.encoding=e.dataset.encoding,this.lang=e.srclang,this.kind=e.kind,this.label=e.label,this.default=e.default,this.needsTransform=!this.src.toLowerCase().endsWith(".vtt")}async parse(){this.body=await o(this.src,this.encoding),this.cues=this.body.split(/\r?\n\r?\n/g).map(c).filter(Boolean)}}async function l(n){const e=[...n.querySelectorAll("track")].map(t=>new d(t));for(const t of e){if(!t.needsTransform)continue;await t.parse(),t.element.remove();const s=n.addTextTrack(t.kind,t.label,t.lang);t.cues.forEach(r=>s.addCue(new VTTCue(r.startTime,r.endTime,r.text))),t.default&&(s.mode="showing")}}document.addEventListener("DOMContentLoaded",()=>[...document.querySelectorAll("video")].forEach(l))})(); 3 | -------------------------------------------------------------------------------- /dist/source.es.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A valid VTT cue 3 | * 4 | * The properties of this class are compatible with `VTTCue` 5 | * and can be used to create a `new VTTCue` instance 6 | * 7 | * *Example* 8 | * ```js 9 | * new VTTCue(cue.startTime, cue.endTime, cue.text); 10 | * ``` 11 | * 12 | * @property {number} number 13 | * @property {number} startTime 14 | * @property {number} endTime 15 | * @property {string} text 16 | */ 17 | class Cue { 18 | /** 19 | * @readonly 20 | * @type {number} 21 | */ 22 | number; 23 | /** 24 | * @readonly 25 | * @type {number} 26 | */ 27 | startTime; 28 | /** 29 | * @readonly 30 | * @type {number} 31 | */ 32 | endTime; 33 | /** 34 | * @readonly 35 | * @type {string} 36 | */ 37 | text; 38 | /** 39 | * 40 | * @param {number} number 41 | * @param {number} startTime 42 | * @param {number} endTime 43 | * @param {string} text 44 | */ 45 | constructor(number, startTime, endTime, text) { 46 | this.number = number; 47 | this.startTime = startTime; 48 | this.endTime = endTime; 49 | this.text = text; 50 | } 51 | } 52 | 53 | /** 54 | * Converts an SRT cue into a VTT compatible cue 55 | * 56 | * For example 57 | * 58 | * ```txt 59 | * 1 60 | * 00:00:00,498 --> 00:00:02,827 61 | * Here's what I love most 62 | * about food and diet. 63 | * ``` 64 | * 65 | * Will be converted into 66 | * 67 | * ```js 68 | * Cue { 69 | * number: 1, 70 | * startTime: 0.498 71 | * endTime: 2.827, 72 | * text: 'Here\'s what I love most\n about food and diet.' 73 | * } 74 | * ``` 75 | * 76 | * @param {string} srtCue 77 | * @returns Cue 78 | */ 79 | function toVttCue(srtCue) { 80 | try { 81 | if( ! srtCue || srtCue === ' ' ) { 82 | return false; 83 | } 84 | const convertedCue = { 85 | number: parseInt(srtCue.match(/^\d+/g)[0]), 86 | timing: { 87 | start: srtCue.match(/(\d+:){2}\d+,\d+/g)[0].replace(',', '.'), 88 | end: srtCue.match(/(\d+:){2}\d+,\d+/g)[1].replace(',', '.') 89 | }, 90 | text: srtCue.split(/\r?\n/g).slice(2, srtCue.split(/\r?\n/g).length).join('\n') 91 | }; 92 | return new Cue(convertedCue.number, hmsToSeconds(convertedCue.timing.start), hmsToSeconds(convertedCue.timing.end), convertedCue.text); 93 | } catch(e) { 94 | return false; 95 | } 96 | } 97 | /** 98 | * Converts a VTT or SRT timing `string` 99 | * to a `number` in seconds + milliseconds 100 | * 101 | * *Example* 102 | * ```js 103 | * const seconds = hmsToSeconds('00:00:02.827'); // 2.827 104 | * ``` 105 | * 106 | * @param {string} str 107 | * @returns number 108 | */ 109 | function hmsToSeconds(str) { 110 | let p = str.split(':'), 111 | s = 0, 112 | m = 1; 113 | while (p.length > 0) { 114 | s += m * parseFloat(p.pop(), 10); 115 | m *= 60; 116 | } 117 | return s; 118 | } 119 | /** 120 | * Fetches the contents of a track source 121 | * 122 | * *Example* 123 | * ```js 124 | * const content = await fetchTrack('https://example.com/path/my-subtitle.srt') 125 | * ``` 126 | * @param {string} src - url 127 | * @param {string} encoding - file encoding format 128 | * @returns Promise 129 | */ 130 | async function fetchTrack(src, encoding = 'utf-8') { 131 | if( ! encoding || encoding === '' ) { 132 | encoding = 'utf-8'; 133 | } 134 | return fetch(src).then(r => r.arrayBuffer()).then(r => new TextDecoder(encoding).decode(r)); 135 | } 136 | 137 | /** 138 | * @property {string} src 139 | * @property {string} encoding 140 | * @property {string} lang 141 | * @property {string} kind 142 | * @property {string} label 143 | * @property {string} default 144 | * @property {string} body 145 | * @property {boolean} needsTransform 146 | * @property {Cue[]} cues 147 | */ 148 | class Track { 149 | /** 150 | * @readonly 151 | * @type {HTMLTrackElement} 152 | */ 153 | element; 154 | /** 155 | * @readonly 156 | * @type {string} 157 | */ 158 | src; 159 | /** 160 | * @readonly 161 | * @type {string} 162 | */ 163 | encoding; 164 | /** 165 | * @readonly 166 | * @type {string} 167 | */ 168 | lang; 169 | /** 170 | * @readonly 171 | * @type {string} 172 | */ 173 | kind; 174 | /** 175 | * @readonly 176 | * @type {string} 177 | */ 178 | label; 179 | /** 180 | * @readonly 181 | * @type {boolean} 182 | */ 183 | default; 184 | /** 185 | * @readonly 186 | * @type {string} 187 | */ 188 | body; 189 | /** 190 | * @readonly 191 | * @type {boolean} 192 | */ 193 | needsTransform; 194 | /** 195 | * @readonly 196 | * @type {Cue[]} 197 | */ 198 | cues = []; 199 | /** 200 | * Parses a `HTMLTrackElement` 201 | * 202 | * @param {HTMLTrackElement} track 203 | */ 204 | constructor(track) { 205 | this.element = track; 206 | this.src = track.src; 207 | this.encoding = track.dataset.encoding; 208 | this.lang = track.srclang; 209 | this.kind = track.kind; 210 | this.label = track.label; 211 | this.default = track.default; 212 | this.needsTransform = !this.src.toLowerCase().endsWith('.vtt'); 213 | } 214 | async parse() { 215 | this.body = await fetchTrack(this.src, this.encoding); 216 | this.cues = this.body.split(/\r?\n\r?\n/g).map(toVttCue).filter(Boolean); 217 | } 218 | } 219 | 220 | /** 221 | * Converts all SRT files into WebVTT files. 222 | * 223 | * @param {HTMLVideoElement} video 224 | */ 225 | async function transformSrtTracks(video) { 226 | const tracks = [...video.querySelectorAll('track')].map(track => new Track(track)); 227 | for (const track of tracks) { 228 | if ( ! track.needsTransform ) continue; 229 | /** 230 | * Fetch track from URL and parse its content 231 | * We need to do before we can use it. 232 | */ 233 | await track.parse(); 234 | /** 235 | * Remove the original 236 | */ 237 | track.element.remove(); 238 | /** 239 | * Add new TextTrack to video 240 | * We later fill this with the transformed data 241 | */ 242 | const t = video.addTextTrack(track.kind, track.label, track.lang); 243 | /** 244 | * Add all cue's we retrieved from the original 245 | * SRT file to the newly created track 246 | */ 247 | track.cues.forEach(cue => t.addCue(new VTTCue(cue.startTime, cue.endTime, cue.text))); 248 | if ( track.default ) { 249 | t.mode = 'showing'; 250 | } 251 | } 252 | } 253 | 254 | document.addEventListener('DOMContentLoaded', () => [...document.querySelectorAll('video')].forEach(transformSrtTracks)); 255 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vite App 7 | 8 | 9 |
10 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /jsr.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@codeit/srt-for-html5-videos", 3 | "version": "2.6.11", 4 | "exports": "./main.d.ts", 5 | "publish": { 6 | "exclude": [ 7 | "./assets", 8 | "./.github" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /main.d.ts: -------------------------------------------------------------------------------- 1 | import { hmsToSeconds } from './src/helpers.js'; 2 | import { toVttCue } from './src/helpers.js'; 3 | import { transformSrtTracks } from './src/transformer.js'; 4 | import { srt2vtt } from './src/helpers.js'; 5 | import { fetchTrack } from './src/helpers.js'; 6 | export { hmsToSeconds, toVttCue, transformSrtTracks, srt2vtt, fetchTrack }; 7 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * _ _ 3 | * (_) (_) 4 | * _ __ _ _ __ _ __ _ 5 | * | '_ \| | '_ \| |/ _` | 6 | * | | | | | | | | | (_| | 7 | * |_| |_|_|_| |_| |\__,_| 8 | * _/ | 9 | * |__/ 10 | */ 11 | import { hmsToSeconds, toVttCue, srt2vtt, fetchTrack } from './src/helpers.js'; 12 | import { transformSrtTracks } from './src/transformer.js'; 13 | 14 | export { 15 | hmsToSeconds, 16 | toVttCue, 17 | transformSrtTracks, 18 | srt2vtt, 19 | fetchTrack 20 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "srt-support-for-html5-videos", 3 | "version": "2.6.10", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "srt-support-for-html5-videos", 9 | "version": "2.6.10", 10 | "devDependencies": { 11 | "rollup-plugin-cleanup": "^3.2.1", 12 | "typescript": "^5.3.3", 13 | "vite": "^5.1.1" 14 | } 15 | }, 16 | "node_modules/@esbuild/aix-ppc64": { 17 | "version": "0.20.2", 18 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", 19 | "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", 20 | "cpu": [ 21 | "ppc64" 22 | ], 23 | "dev": true, 24 | "optional": true, 25 | "os": [ 26 | "aix" 27 | ], 28 | "engines": { 29 | "node": ">=12" 30 | } 31 | }, 32 | "node_modules/@esbuild/android-arm": { 33 | "version": "0.20.2", 34 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", 35 | "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", 36 | "cpu": [ 37 | "arm" 38 | ], 39 | "dev": true, 40 | "optional": true, 41 | "os": [ 42 | "android" 43 | ], 44 | "engines": { 45 | "node": ">=12" 46 | } 47 | }, 48 | "node_modules/@esbuild/android-arm64": { 49 | "version": "0.20.2", 50 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", 51 | "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", 52 | "cpu": [ 53 | "arm64" 54 | ], 55 | "dev": true, 56 | "optional": true, 57 | "os": [ 58 | "android" 59 | ], 60 | "engines": { 61 | "node": ">=12" 62 | } 63 | }, 64 | "node_modules/@esbuild/android-x64": { 65 | "version": "0.20.2", 66 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", 67 | "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", 68 | "cpu": [ 69 | "x64" 70 | ], 71 | "dev": true, 72 | "optional": true, 73 | "os": [ 74 | "android" 75 | ], 76 | "engines": { 77 | "node": ">=12" 78 | } 79 | }, 80 | "node_modules/@esbuild/darwin-arm64": { 81 | "version": "0.20.2", 82 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", 83 | "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", 84 | "cpu": [ 85 | "arm64" 86 | ], 87 | "dev": true, 88 | "optional": true, 89 | "os": [ 90 | "darwin" 91 | ], 92 | "engines": { 93 | "node": ">=12" 94 | } 95 | }, 96 | "node_modules/@esbuild/darwin-x64": { 97 | "version": "0.20.2", 98 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", 99 | "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", 100 | "cpu": [ 101 | "x64" 102 | ], 103 | "dev": true, 104 | "optional": true, 105 | "os": [ 106 | "darwin" 107 | ], 108 | "engines": { 109 | "node": ">=12" 110 | } 111 | }, 112 | "node_modules/@esbuild/freebsd-arm64": { 113 | "version": "0.20.2", 114 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", 115 | "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", 116 | "cpu": [ 117 | "arm64" 118 | ], 119 | "dev": true, 120 | "optional": true, 121 | "os": [ 122 | "freebsd" 123 | ], 124 | "engines": { 125 | "node": ">=12" 126 | } 127 | }, 128 | "node_modules/@esbuild/freebsd-x64": { 129 | "version": "0.20.2", 130 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", 131 | "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", 132 | "cpu": [ 133 | "x64" 134 | ], 135 | "dev": true, 136 | "optional": true, 137 | "os": [ 138 | "freebsd" 139 | ], 140 | "engines": { 141 | "node": ">=12" 142 | } 143 | }, 144 | "node_modules/@esbuild/linux-arm": { 145 | "version": "0.20.2", 146 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", 147 | "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", 148 | "cpu": [ 149 | "arm" 150 | ], 151 | "dev": true, 152 | "optional": true, 153 | "os": [ 154 | "linux" 155 | ], 156 | "engines": { 157 | "node": ">=12" 158 | } 159 | }, 160 | "node_modules/@esbuild/linux-arm64": { 161 | "version": "0.20.2", 162 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", 163 | "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", 164 | "cpu": [ 165 | "arm64" 166 | ], 167 | "dev": true, 168 | "optional": true, 169 | "os": [ 170 | "linux" 171 | ], 172 | "engines": { 173 | "node": ">=12" 174 | } 175 | }, 176 | "node_modules/@esbuild/linux-ia32": { 177 | "version": "0.20.2", 178 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", 179 | "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", 180 | "cpu": [ 181 | "ia32" 182 | ], 183 | "dev": true, 184 | "optional": true, 185 | "os": [ 186 | "linux" 187 | ], 188 | "engines": { 189 | "node": ">=12" 190 | } 191 | }, 192 | "node_modules/@esbuild/linux-loong64": { 193 | "version": "0.20.2", 194 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", 195 | "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", 196 | "cpu": [ 197 | "loong64" 198 | ], 199 | "dev": true, 200 | "optional": true, 201 | "os": [ 202 | "linux" 203 | ], 204 | "engines": { 205 | "node": ">=12" 206 | } 207 | }, 208 | "node_modules/@esbuild/linux-mips64el": { 209 | "version": "0.20.2", 210 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", 211 | "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", 212 | "cpu": [ 213 | "mips64el" 214 | ], 215 | "dev": true, 216 | "optional": true, 217 | "os": [ 218 | "linux" 219 | ], 220 | "engines": { 221 | "node": ">=12" 222 | } 223 | }, 224 | "node_modules/@esbuild/linux-ppc64": { 225 | "version": "0.20.2", 226 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", 227 | "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", 228 | "cpu": [ 229 | "ppc64" 230 | ], 231 | "dev": true, 232 | "optional": true, 233 | "os": [ 234 | "linux" 235 | ], 236 | "engines": { 237 | "node": ">=12" 238 | } 239 | }, 240 | "node_modules/@esbuild/linux-riscv64": { 241 | "version": "0.20.2", 242 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", 243 | "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", 244 | "cpu": [ 245 | "riscv64" 246 | ], 247 | "dev": true, 248 | "optional": true, 249 | "os": [ 250 | "linux" 251 | ], 252 | "engines": { 253 | "node": ">=12" 254 | } 255 | }, 256 | "node_modules/@esbuild/linux-s390x": { 257 | "version": "0.20.2", 258 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", 259 | "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", 260 | "cpu": [ 261 | "s390x" 262 | ], 263 | "dev": true, 264 | "optional": true, 265 | "os": [ 266 | "linux" 267 | ], 268 | "engines": { 269 | "node": ">=12" 270 | } 271 | }, 272 | "node_modules/@esbuild/linux-x64": { 273 | "version": "0.20.2", 274 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", 275 | "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", 276 | "cpu": [ 277 | "x64" 278 | ], 279 | "dev": true, 280 | "optional": true, 281 | "os": [ 282 | "linux" 283 | ], 284 | "engines": { 285 | "node": ">=12" 286 | } 287 | }, 288 | "node_modules/@esbuild/netbsd-x64": { 289 | "version": "0.20.2", 290 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", 291 | "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", 292 | "cpu": [ 293 | "x64" 294 | ], 295 | "dev": true, 296 | "optional": true, 297 | "os": [ 298 | "netbsd" 299 | ], 300 | "engines": { 301 | "node": ">=12" 302 | } 303 | }, 304 | "node_modules/@esbuild/openbsd-x64": { 305 | "version": "0.20.2", 306 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", 307 | "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", 308 | "cpu": [ 309 | "x64" 310 | ], 311 | "dev": true, 312 | "optional": true, 313 | "os": [ 314 | "openbsd" 315 | ], 316 | "engines": { 317 | "node": ">=12" 318 | } 319 | }, 320 | "node_modules/@esbuild/sunos-x64": { 321 | "version": "0.20.2", 322 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", 323 | "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", 324 | "cpu": [ 325 | "x64" 326 | ], 327 | "dev": true, 328 | "optional": true, 329 | "os": [ 330 | "sunos" 331 | ], 332 | "engines": { 333 | "node": ">=12" 334 | } 335 | }, 336 | "node_modules/@esbuild/win32-arm64": { 337 | "version": "0.20.2", 338 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", 339 | "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", 340 | "cpu": [ 341 | "arm64" 342 | ], 343 | "dev": true, 344 | "optional": true, 345 | "os": [ 346 | "win32" 347 | ], 348 | "engines": { 349 | "node": ">=12" 350 | } 351 | }, 352 | "node_modules/@esbuild/win32-ia32": { 353 | "version": "0.20.2", 354 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", 355 | "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", 356 | "cpu": [ 357 | "ia32" 358 | ], 359 | "dev": true, 360 | "optional": true, 361 | "os": [ 362 | "win32" 363 | ], 364 | "engines": { 365 | "node": ">=12" 366 | } 367 | }, 368 | "node_modules/@esbuild/win32-x64": { 369 | "version": "0.20.2", 370 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", 371 | "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", 372 | "cpu": [ 373 | "x64" 374 | ], 375 | "dev": true, 376 | "optional": true, 377 | "os": [ 378 | "win32" 379 | ], 380 | "engines": { 381 | "node": ">=12" 382 | } 383 | }, 384 | "node_modules/@rollup/rollup-android-arm-eabi": { 385 | "version": "4.18.0", 386 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", 387 | "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", 388 | "cpu": [ 389 | "arm" 390 | ], 391 | "dev": true, 392 | "optional": true, 393 | "os": [ 394 | "android" 395 | ] 396 | }, 397 | "node_modules/@rollup/rollup-android-arm64": { 398 | "version": "4.18.0", 399 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", 400 | "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", 401 | "cpu": [ 402 | "arm64" 403 | ], 404 | "dev": true, 405 | "optional": true, 406 | "os": [ 407 | "android" 408 | ] 409 | }, 410 | "node_modules/@rollup/rollup-darwin-arm64": { 411 | "version": "4.18.0", 412 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", 413 | "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", 414 | "cpu": [ 415 | "arm64" 416 | ], 417 | "dev": true, 418 | "optional": true, 419 | "os": [ 420 | "darwin" 421 | ] 422 | }, 423 | "node_modules/@rollup/rollup-darwin-x64": { 424 | "version": "4.18.0", 425 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", 426 | "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", 427 | "cpu": [ 428 | "x64" 429 | ], 430 | "dev": true, 431 | "optional": true, 432 | "os": [ 433 | "darwin" 434 | ] 435 | }, 436 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 437 | "version": "4.18.0", 438 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", 439 | "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", 440 | "cpu": [ 441 | "arm" 442 | ], 443 | "dev": true, 444 | "optional": true, 445 | "os": [ 446 | "linux" 447 | ] 448 | }, 449 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 450 | "version": "4.18.0", 451 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", 452 | "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", 453 | "cpu": [ 454 | "arm" 455 | ], 456 | "dev": true, 457 | "optional": true, 458 | "os": [ 459 | "linux" 460 | ] 461 | }, 462 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 463 | "version": "4.18.0", 464 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", 465 | "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", 466 | "cpu": [ 467 | "arm64" 468 | ], 469 | "dev": true, 470 | "optional": true, 471 | "os": [ 472 | "linux" 473 | ] 474 | }, 475 | "node_modules/@rollup/rollup-linux-arm64-musl": { 476 | "version": "4.18.0", 477 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", 478 | "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", 479 | "cpu": [ 480 | "arm64" 481 | ], 482 | "dev": true, 483 | "optional": true, 484 | "os": [ 485 | "linux" 486 | ] 487 | }, 488 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 489 | "version": "4.18.0", 490 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", 491 | "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", 492 | "cpu": [ 493 | "ppc64" 494 | ], 495 | "dev": true, 496 | "optional": true, 497 | "os": [ 498 | "linux" 499 | ] 500 | }, 501 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 502 | "version": "4.18.0", 503 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", 504 | "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", 505 | "cpu": [ 506 | "riscv64" 507 | ], 508 | "dev": true, 509 | "optional": true, 510 | "os": [ 511 | "linux" 512 | ] 513 | }, 514 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 515 | "version": "4.18.0", 516 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", 517 | "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", 518 | "cpu": [ 519 | "s390x" 520 | ], 521 | "dev": true, 522 | "optional": true, 523 | "os": [ 524 | "linux" 525 | ] 526 | }, 527 | "node_modules/@rollup/rollup-linux-x64-gnu": { 528 | "version": "4.18.0", 529 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", 530 | "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", 531 | "cpu": [ 532 | "x64" 533 | ], 534 | "dev": true, 535 | "optional": true, 536 | "os": [ 537 | "linux" 538 | ] 539 | }, 540 | "node_modules/@rollup/rollup-linux-x64-musl": { 541 | "version": "4.18.0", 542 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", 543 | "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", 544 | "cpu": [ 545 | "x64" 546 | ], 547 | "dev": true, 548 | "optional": true, 549 | "os": [ 550 | "linux" 551 | ] 552 | }, 553 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 554 | "version": "4.18.0", 555 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", 556 | "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", 557 | "cpu": [ 558 | "arm64" 559 | ], 560 | "dev": true, 561 | "optional": true, 562 | "os": [ 563 | "win32" 564 | ] 565 | }, 566 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 567 | "version": "4.18.0", 568 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", 569 | "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", 570 | "cpu": [ 571 | "ia32" 572 | ], 573 | "dev": true, 574 | "optional": true, 575 | "os": [ 576 | "win32" 577 | ] 578 | }, 579 | "node_modules/@rollup/rollup-win32-x64-msvc": { 580 | "version": "4.18.0", 581 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", 582 | "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", 583 | "cpu": [ 584 | "x64" 585 | ], 586 | "dev": true, 587 | "optional": true, 588 | "os": [ 589 | "win32" 590 | ] 591 | }, 592 | "node_modules/@types/estree": { 593 | "version": "1.0.5", 594 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 595 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 596 | "dev": true 597 | }, 598 | "node_modules/esbuild": { 599 | "version": "0.20.2", 600 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", 601 | "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", 602 | "dev": true, 603 | "hasInstallScript": true, 604 | "bin": { 605 | "esbuild": "bin/esbuild" 606 | }, 607 | "engines": { 608 | "node": ">=12" 609 | }, 610 | "optionalDependencies": { 611 | "@esbuild/aix-ppc64": "0.20.2", 612 | "@esbuild/android-arm": "0.20.2", 613 | "@esbuild/android-arm64": "0.20.2", 614 | "@esbuild/android-x64": "0.20.2", 615 | "@esbuild/darwin-arm64": "0.20.2", 616 | "@esbuild/darwin-x64": "0.20.2", 617 | "@esbuild/freebsd-arm64": "0.20.2", 618 | "@esbuild/freebsd-x64": "0.20.2", 619 | "@esbuild/linux-arm": "0.20.2", 620 | "@esbuild/linux-arm64": "0.20.2", 621 | "@esbuild/linux-ia32": "0.20.2", 622 | "@esbuild/linux-loong64": "0.20.2", 623 | "@esbuild/linux-mips64el": "0.20.2", 624 | "@esbuild/linux-ppc64": "0.20.2", 625 | "@esbuild/linux-riscv64": "0.20.2", 626 | "@esbuild/linux-s390x": "0.20.2", 627 | "@esbuild/linux-x64": "0.20.2", 628 | "@esbuild/netbsd-x64": "0.20.2", 629 | "@esbuild/openbsd-x64": "0.20.2", 630 | "@esbuild/sunos-x64": "0.20.2", 631 | "@esbuild/win32-arm64": "0.20.2", 632 | "@esbuild/win32-ia32": "0.20.2", 633 | "@esbuild/win32-x64": "0.20.2" 634 | } 635 | }, 636 | "node_modules/estree-walker": { 637 | "version": "0.6.1", 638 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 639 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 640 | "dev": true 641 | }, 642 | "node_modules/fsevents": { 643 | "version": "2.3.3", 644 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 645 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 646 | "dev": true, 647 | "hasInstallScript": true, 648 | "optional": true, 649 | "os": [ 650 | "darwin" 651 | ], 652 | "engines": { 653 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 654 | } 655 | }, 656 | "node_modules/js-cleanup": { 657 | "version": "1.2.0", 658 | "resolved": "https://registry.npmjs.org/js-cleanup/-/js-cleanup-1.2.0.tgz", 659 | "integrity": "sha512-JeDD0yiiSt80fXzAVa/crrS0JDPQljyBG/RpOtaSbyDq03VHa9szJWMaWOYU/bcTn412uMN2MxApXq8v79cUiQ==", 660 | "dev": true, 661 | "dependencies": { 662 | "magic-string": "^0.25.7", 663 | "perf-regexes": "^1.0.1", 664 | "skip-regex": "^1.0.2" 665 | }, 666 | "engines": { 667 | "node": "^10.14.2 || >=12.0.0" 668 | } 669 | }, 670 | "node_modules/magic-string": { 671 | "version": "0.25.9", 672 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", 673 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 674 | "dev": true, 675 | "dependencies": { 676 | "sourcemap-codec": "^1.4.8" 677 | } 678 | }, 679 | "node_modules/nanoid": { 680 | "version": "3.3.7", 681 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 682 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 683 | "dev": true, 684 | "funding": [ 685 | { 686 | "type": "github", 687 | "url": "https://github.com/sponsors/ai" 688 | } 689 | ], 690 | "bin": { 691 | "nanoid": "bin/nanoid.cjs" 692 | }, 693 | "engines": { 694 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 695 | } 696 | }, 697 | "node_modules/perf-regexes": { 698 | "version": "1.0.1", 699 | "resolved": "https://registry.npmjs.org/perf-regexes/-/perf-regexes-1.0.1.tgz", 700 | "integrity": "sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==", 701 | "dev": true, 702 | "engines": { 703 | "node": ">=6.14" 704 | } 705 | }, 706 | "node_modules/picocolors": { 707 | "version": "1.0.1", 708 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 709 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", 710 | "dev": true 711 | }, 712 | "node_modules/postcss": { 713 | "version": "8.4.38", 714 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", 715 | "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", 716 | "dev": true, 717 | "funding": [ 718 | { 719 | "type": "opencollective", 720 | "url": "https://opencollective.com/postcss/" 721 | }, 722 | { 723 | "type": "tidelift", 724 | "url": "https://tidelift.com/funding/github/npm/postcss" 725 | }, 726 | { 727 | "type": "github", 728 | "url": "https://github.com/sponsors/ai" 729 | } 730 | ], 731 | "dependencies": { 732 | "nanoid": "^3.3.7", 733 | "picocolors": "^1.0.0", 734 | "source-map-js": "^1.2.0" 735 | }, 736 | "engines": { 737 | "node": "^10 || ^12 || >=14" 738 | } 739 | }, 740 | "node_modules/rollup": { 741 | "version": "4.18.0", 742 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", 743 | "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", 744 | "dev": true, 745 | "dependencies": { 746 | "@types/estree": "1.0.5" 747 | }, 748 | "bin": { 749 | "rollup": "dist/bin/rollup" 750 | }, 751 | "engines": { 752 | "node": ">=18.0.0", 753 | "npm": ">=8.0.0" 754 | }, 755 | "optionalDependencies": { 756 | "@rollup/rollup-android-arm-eabi": "4.18.0", 757 | "@rollup/rollup-android-arm64": "4.18.0", 758 | "@rollup/rollup-darwin-arm64": "4.18.0", 759 | "@rollup/rollup-darwin-x64": "4.18.0", 760 | "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", 761 | "@rollup/rollup-linux-arm-musleabihf": "4.18.0", 762 | "@rollup/rollup-linux-arm64-gnu": "4.18.0", 763 | "@rollup/rollup-linux-arm64-musl": "4.18.0", 764 | "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", 765 | "@rollup/rollup-linux-riscv64-gnu": "4.18.0", 766 | "@rollup/rollup-linux-s390x-gnu": "4.18.0", 767 | "@rollup/rollup-linux-x64-gnu": "4.18.0", 768 | "@rollup/rollup-linux-x64-musl": "4.18.0", 769 | "@rollup/rollup-win32-arm64-msvc": "4.18.0", 770 | "@rollup/rollup-win32-ia32-msvc": "4.18.0", 771 | "@rollup/rollup-win32-x64-msvc": "4.18.0", 772 | "fsevents": "~2.3.2" 773 | } 774 | }, 775 | "node_modules/rollup-plugin-cleanup": { 776 | "version": "3.2.1", 777 | "resolved": "https://registry.npmjs.org/rollup-plugin-cleanup/-/rollup-plugin-cleanup-3.2.1.tgz", 778 | "integrity": "sha512-zuv8EhoO3TpnrU8MX8W7YxSbO4gmOR0ny06Lm3nkFfq0IVKdBUtHwhVzY1OAJyNCIAdLiyPnOrU0KnO0Fri1GQ==", 779 | "dev": true, 780 | "dependencies": { 781 | "js-cleanup": "^1.2.0", 782 | "rollup-pluginutils": "^2.8.2" 783 | }, 784 | "engines": { 785 | "node": "^10.14.2 || >=12.0.0" 786 | }, 787 | "peerDependencies": { 788 | "rollup": ">=2.0" 789 | } 790 | }, 791 | "node_modules/rollup-pluginutils": { 792 | "version": "2.8.2", 793 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 794 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 795 | "dev": true, 796 | "dependencies": { 797 | "estree-walker": "^0.6.1" 798 | } 799 | }, 800 | "node_modules/skip-regex": { 801 | "version": "1.0.2", 802 | "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", 803 | "integrity": "sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==", 804 | "dev": true, 805 | "engines": { 806 | "node": ">=4.2" 807 | } 808 | }, 809 | "node_modules/source-map-js": { 810 | "version": "1.2.0", 811 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 812 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 813 | "dev": true, 814 | "engines": { 815 | "node": ">=0.10.0" 816 | } 817 | }, 818 | "node_modules/sourcemap-codec": { 819 | "version": "1.4.8", 820 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 821 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 822 | "deprecated": "Please use @jridgewell/sourcemap-codec instead", 823 | "dev": true 824 | }, 825 | "node_modules/typescript": { 826 | "version": "5.4.5", 827 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", 828 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", 829 | "dev": true, 830 | "bin": { 831 | "tsc": "bin/tsc", 832 | "tsserver": "bin/tsserver" 833 | }, 834 | "engines": { 835 | "node": ">=14.17" 836 | } 837 | }, 838 | "node_modules/vite": { 839 | "version": "5.2.12", 840 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", 841 | "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", 842 | "dev": true, 843 | "dependencies": { 844 | "esbuild": "^0.20.1", 845 | "postcss": "^8.4.38", 846 | "rollup": "^4.13.0" 847 | }, 848 | "bin": { 849 | "vite": "bin/vite.js" 850 | }, 851 | "engines": { 852 | "node": "^18.0.0 || >=20.0.0" 853 | }, 854 | "funding": { 855 | "url": "https://github.com/vitejs/vite?sponsor=1" 856 | }, 857 | "optionalDependencies": { 858 | "fsevents": "~2.3.3" 859 | }, 860 | "peerDependencies": { 861 | "@types/node": "^18.0.0 || >=20.0.0", 862 | "less": "*", 863 | "lightningcss": "^1.21.0", 864 | "sass": "*", 865 | "stylus": "*", 866 | "sugarss": "*", 867 | "terser": "^5.4.0" 868 | }, 869 | "peerDependenciesMeta": { 870 | "@types/node": { 871 | "optional": true 872 | }, 873 | "less": { 874 | "optional": true 875 | }, 876 | "lightningcss": { 877 | "optional": true 878 | }, 879 | "sass": { 880 | "optional": true 881 | }, 882 | "stylus": { 883 | "optional": true 884 | }, 885 | "sugarss": { 886 | "optional": true 887 | }, 888 | "terser": { 889 | "optional": true 890 | } 891 | } 892 | } 893 | }, 894 | "dependencies": { 895 | "@esbuild/aix-ppc64": { 896 | "version": "0.20.2", 897 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", 898 | "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", 899 | "dev": true, 900 | "optional": true 901 | }, 902 | "@esbuild/android-arm": { 903 | "version": "0.20.2", 904 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", 905 | "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", 906 | "dev": true, 907 | "optional": true 908 | }, 909 | "@esbuild/android-arm64": { 910 | "version": "0.20.2", 911 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", 912 | "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", 913 | "dev": true, 914 | "optional": true 915 | }, 916 | "@esbuild/android-x64": { 917 | "version": "0.20.2", 918 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", 919 | "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", 920 | "dev": true, 921 | "optional": true 922 | }, 923 | "@esbuild/darwin-arm64": { 924 | "version": "0.20.2", 925 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", 926 | "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", 927 | "dev": true, 928 | "optional": true 929 | }, 930 | "@esbuild/darwin-x64": { 931 | "version": "0.20.2", 932 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", 933 | "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", 934 | "dev": true, 935 | "optional": true 936 | }, 937 | "@esbuild/freebsd-arm64": { 938 | "version": "0.20.2", 939 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", 940 | "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", 941 | "dev": true, 942 | "optional": true 943 | }, 944 | "@esbuild/freebsd-x64": { 945 | "version": "0.20.2", 946 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", 947 | "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", 948 | "dev": true, 949 | "optional": true 950 | }, 951 | "@esbuild/linux-arm": { 952 | "version": "0.20.2", 953 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", 954 | "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", 955 | "dev": true, 956 | "optional": true 957 | }, 958 | "@esbuild/linux-arm64": { 959 | "version": "0.20.2", 960 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", 961 | "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", 962 | "dev": true, 963 | "optional": true 964 | }, 965 | "@esbuild/linux-ia32": { 966 | "version": "0.20.2", 967 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", 968 | "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", 969 | "dev": true, 970 | "optional": true 971 | }, 972 | "@esbuild/linux-loong64": { 973 | "version": "0.20.2", 974 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", 975 | "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", 976 | "dev": true, 977 | "optional": true 978 | }, 979 | "@esbuild/linux-mips64el": { 980 | "version": "0.20.2", 981 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", 982 | "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", 983 | "dev": true, 984 | "optional": true 985 | }, 986 | "@esbuild/linux-ppc64": { 987 | "version": "0.20.2", 988 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", 989 | "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", 990 | "dev": true, 991 | "optional": true 992 | }, 993 | "@esbuild/linux-riscv64": { 994 | "version": "0.20.2", 995 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", 996 | "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", 997 | "dev": true, 998 | "optional": true 999 | }, 1000 | "@esbuild/linux-s390x": { 1001 | "version": "0.20.2", 1002 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", 1003 | "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", 1004 | "dev": true, 1005 | "optional": true 1006 | }, 1007 | "@esbuild/linux-x64": { 1008 | "version": "0.20.2", 1009 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", 1010 | "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", 1011 | "dev": true, 1012 | "optional": true 1013 | }, 1014 | "@esbuild/netbsd-x64": { 1015 | "version": "0.20.2", 1016 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", 1017 | "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", 1018 | "dev": true, 1019 | "optional": true 1020 | }, 1021 | "@esbuild/openbsd-x64": { 1022 | "version": "0.20.2", 1023 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", 1024 | "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", 1025 | "dev": true, 1026 | "optional": true 1027 | }, 1028 | "@esbuild/sunos-x64": { 1029 | "version": "0.20.2", 1030 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", 1031 | "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", 1032 | "dev": true, 1033 | "optional": true 1034 | }, 1035 | "@esbuild/win32-arm64": { 1036 | "version": "0.20.2", 1037 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", 1038 | "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", 1039 | "dev": true, 1040 | "optional": true 1041 | }, 1042 | "@esbuild/win32-ia32": { 1043 | "version": "0.20.2", 1044 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", 1045 | "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", 1046 | "dev": true, 1047 | "optional": true 1048 | }, 1049 | "@esbuild/win32-x64": { 1050 | "version": "0.20.2", 1051 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", 1052 | "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", 1053 | "dev": true, 1054 | "optional": true 1055 | }, 1056 | "@rollup/rollup-android-arm-eabi": { 1057 | "version": "4.18.0", 1058 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", 1059 | "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", 1060 | "dev": true, 1061 | "optional": true 1062 | }, 1063 | "@rollup/rollup-android-arm64": { 1064 | "version": "4.18.0", 1065 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", 1066 | "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", 1067 | "dev": true, 1068 | "optional": true 1069 | }, 1070 | "@rollup/rollup-darwin-arm64": { 1071 | "version": "4.18.0", 1072 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", 1073 | "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", 1074 | "dev": true, 1075 | "optional": true 1076 | }, 1077 | "@rollup/rollup-darwin-x64": { 1078 | "version": "4.18.0", 1079 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", 1080 | "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", 1081 | "dev": true, 1082 | "optional": true 1083 | }, 1084 | "@rollup/rollup-linux-arm-gnueabihf": { 1085 | "version": "4.18.0", 1086 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", 1087 | "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", 1088 | "dev": true, 1089 | "optional": true 1090 | }, 1091 | "@rollup/rollup-linux-arm-musleabihf": { 1092 | "version": "4.18.0", 1093 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", 1094 | "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", 1095 | "dev": true, 1096 | "optional": true 1097 | }, 1098 | "@rollup/rollup-linux-arm64-gnu": { 1099 | "version": "4.18.0", 1100 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", 1101 | "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", 1102 | "dev": true, 1103 | "optional": true 1104 | }, 1105 | "@rollup/rollup-linux-arm64-musl": { 1106 | "version": "4.18.0", 1107 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", 1108 | "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", 1109 | "dev": true, 1110 | "optional": true 1111 | }, 1112 | "@rollup/rollup-linux-powerpc64le-gnu": { 1113 | "version": "4.18.0", 1114 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", 1115 | "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", 1116 | "dev": true, 1117 | "optional": true 1118 | }, 1119 | "@rollup/rollup-linux-riscv64-gnu": { 1120 | "version": "4.18.0", 1121 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", 1122 | "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", 1123 | "dev": true, 1124 | "optional": true 1125 | }, 1126 | "@rollup/rollup-linux-s390x-gnu": { 1127 | "version": "4.18.0", 1128 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", 1129 | "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", 1130 | "dev": true, 1131 | "optional": true 1132 | }, 1133 | "@rollup/rollup-linux-x64-gnu": { 1134 | "version": "4.18.0", 1135 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", 1136 | "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", 1137 | "dev": true, 1138 | "optional": true 1139 | }, 1140 | "@rollup/rollup-linux-x64-musl": { 1141 | "version": "4.18.0", 1142 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", 1143 | "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", 1144 | "dev": true, 1145 | "optional": true 1146 | }, 1147 | "@rollup/rollup-win32-arm64-msvc": { 1148 | "version": "4.18.0", 1149 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", 1150 | "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", 1151 | "dev": true, 1152 | "optional": true 1153 | }, 1154 | "@rollup/rollup-win32-ia32-msvc": { 1155 | "version": "4.18.0", 1156 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", 1157 | "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", 1158 | "dev": true, 1159 | "optional": true 1160 | }, 1161 | "@rollup/rollup-win32-x64-msvc": { 1162 | "version": "4.18.0", 1163 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", 1164 | "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", 1165 | "dev": true, 1166 | "optional": true 1167 | }, 1168 | "@types/estree": { 1169 | "version": "1.0.5", 1170 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 1171 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 1172 | "dev": true 1173 | }, 1174 | "esbuild": { 1175 | "version": "0.20.2", 1176 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", 1177 | "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", 1178 | "dev": true, 1179 | "requires": { 1180 | "@esbuild/aix-ppc64": "0.20.2", 1181 | "@esbuild/android-arm": "0.20.2", 1182 | "@esbuild/android-arm64": "0.20.2", 1183 | "@esbuild/android-x64": "0.20.2", 1184 | "@esbuild/darwin-arm64": "0.20.2", 1185 | "@esbuild/darwin-x64": "0.20.2", 1186 | "@esbuild/freebsd-arm64": "0.20.2", 1187 | "@esbuild/freebsd-x64": "0.20.2", 1188 | "@esbuild/linux-arm": "0.20.2", 1189 | "@esbuild/linux-arm64": "0.20.2", 1190 | "@esbuild/linux-ia32": "0.20.2", 1191 | "@esbuild/linux-loong64": "0.20.2", 1192 | "@esbuild/linux-mips64el": "0.20.2", 1193 | "@esbuild/linux-ppc64": "0.20.2", 1194 | "@esbuild/linux-riscv64": "0.20.2", 1195 | "@esbuild/linux-s390x": "0.20.2", 1196 | "@esbuild/linux-x64": "0.20.2", 1197 | "@esbuild/netbsd-x64": "0.20.2", 1198 | "@esbuild/openbsd-x64": "0.20.2", 1199 | "@esbuild/sunos-x64": "0.20.2", 1200 | "@esbuild/win32-arm64": "0.20.2", 1201 | "@esbuild/win32-ia32": "0.20.2", 1202 | "@esbuild/win32-x64": "0.20.2" 1203 | } 1204 | }, 1205 | "estree-walker": { 1206 | "version": "0.6.1", 1207 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 1208 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 1209 | "dev": true 1210 | }, 1211 | "fsevents": { 1212 | "version": "2.3.3", 1213 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1214 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1215 | "dev": true, 1216 | "optional": true 1217 | }, 1218 | "js-cleanup": { 1219 | "version": "1.2.0", 1220 | "resolved": "https://registry.npmjs.org/js-cleanup/-/js-cleanup-1.2.0.tgz", 1221 | "integrity": "sha512-JeDD0yiiSt80fXzAVa/crrS0JDPQljyBG/RpOtaSbyDq03VHa9szJWMaWOYU/bcTn412uMN2MxApXq8v79cUiQ==", 1222 | "dev": true, 1223 | "requires": { 1224 | "magic-string": "^0.25.7", 1225 | "perf-regexes": "^1.0.1", 1226 | "skip-regex": "^1.0.2" 1227 | } 1228 | }, 1229 | "magic-string": { 1230 | "version": "0.25.9", 1231 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", 1232 | "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", 1233 | "dev": true, 1234 | "requires": { 1235 | "sourcemap-codec": "^1.4.8" 1236 | } 1237 | }, 1238 | "nanoid": { 1239 | "version": "3.3.7", 1240 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1241 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1242 | "dev": true 1243 | }, 1244 | "perf-regexes": { 1245 | "version": "1.0.1", 1246 | "resolved": "https://registry.npmjs.org/perf-regexes/-/perf-regexes-1.0.1.tgz", 1247 | "integrity": "sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==", 1248 | "dev": true 1249 | }, 1250 | "picocolors": { 1251 | "version": "1.0.1", 1252 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", 1253 | "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", 1254 | "dev": true 1255 | }, 1256 | "postcss": { 1257 | "version": "8.4.38", 1258 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", 1259 | "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", 1260 | "dev": true, 1261 | "requires": { 1262 | "nanoid": "^3.3.7", 1263 | "picocolors": "^1.0.0", 1264 | "source-map-js": "^1.2.0" 1265 | } 1266 | }, 1267 | "rollup": { 1268 | "version": "4.18.0", 1269 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", 1270 | "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", 1271 | "dev": true, 1272 | "requires": { 1273 | "@rollup/rollup-android-arm-eabi": "4.18.0", 1274 | "@rollup/rollup-android-arm64": "4.18.0", 1275 | "@rollup/rollup-darwin-arm64": "4.18.0", 1276 | "@rollup/rollup-darwin-x64": "4.18.0", 1277 | "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", 1278 | "@rollup/rollup-linux-arm-musleabihf": "4.18.0", 1279 | "@rollup/rollup-linux-arm64-gnu": "4.18.0", 1280 | "@rollup/rollup-linux-arm64-musl": "4.18.0", 1281 | "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", 1282 | "@rollup/rollup-linux-riscv64-gnu": "4.18.0", 1283 | "@rollup/rollup-linux-s390x-gnu": "4.18.0", 1284 | "@rollup/rollup-linux-x64-gnu": "4.18.0", 1285 | "@rollup/rollup-linux-x64-musl": "4.18.0", 1286 | "@rollup/rollup-win32-arm64-msvc": "4.18.0", 1287 | "@rollup/rollup-win32-ia32-msvc": "4.18.0", 1288 | "@rollup/rollup-win32-x64-msvc": "4.18.0", 1289 | "@types/estree": "1.0.5", 1290 | "fsevents": "~2.3.2" 1291 | } 1292 | }, 1293 | "rollup-plugin-cleanup": { 1294 | "version": "3.2.1", 1295 | "resolved": "https://registry.npmjs.org/rollup-plugin-cleanup/-/rollup-plugin-cleanup-3.2.1.tgz", 1296 | "integrity": "sha512-zuv8EhoO3TpnrU8MX8W7YxSbO4gmOR0ny06Lm3nkFfq0IVKdBUtHwhVzY1OAJyNCIAdLiyPnOrU0KnO0Fri1GQ==", 1297 | "dev": true, 1298 | "requires": { 1299 | "js-cleanup": "^1.2.0", 1300 | "rollup-pluginutils": "^2.8.2" 1301 | } 1302 | }, 1303 | "rollup-pluginutils": { 1304 | "version": "2.8.2", 1305 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 1306 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 1307 | "dev": true, 1308 | "requires": { 1309 | "estree-walker": "^0.6.1" 1310 | } 1311 | }, 1312 | "skip-regex": { 1313 | "version": "1.0.2", 1314 | "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", 1315 | "integrity": "sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==", 1316 | "dev": true 1317 | }, 1318 | "source-map-js": { 1319 | "version": "1.2.0", 1320 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", 1321 | "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", 1322 | "dev": true 1323 | }, 1324 | "sourcemap-codec": { 1325 | "version": "1.4.8", 1326 | "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", 1327 | "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", 1328 | "dev": true 1329 | }, 1330 | "typescript": { 1331 | "version": "5.4.5", 1332 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", 1333 | "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", 1334 | "dev": true 1335 | }, 1336 | "vite": { 1337 | "version": "5.2.12", 1338 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", 1339 | "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", 1340 | "dev": true, 1341 | "requires": { 1342 | "esbuild": "^0.20.1", 1343 | "fsevents": "~2.3.3", 1344 | "postcss": "^8.4.38", 1345 | "rollup": "^4.13.0" 1346 | } 1347 | } 1348 | } 1349 | } 1350 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "srt-support-for-html5-videos", 3 | "version": "2.6.11", 4 | "repository": "https://github.com/codeit-ninja/SRT-Support-for-HTML5-videos", 5 | "type": "module", 6 | "main": "main.js", 7 | "types": "main.d.ts", 8 | "author": { 9 | "email": "richard@codeit.ninja", 10 | "name": "Richard", 11 | "url": "https://codeit.ninja" 12 | }, 13 | "scripts": { 14 | "dev": "vite", 15 | "build": "rm -rf ./dist && npm run build:iife && npm run build:esm && npm run build:source && tsc --allowJs --declaration --declarationDir . --outDir temp main.js && rm -rf temp", 16 | "build:source": "vite --config vite.config.js build", 17 | "build:iife": "vite --config vite.config.iife.js build", 18 | "build:esm": "vite --config vite.config.esm.js build", 19 | "preview": "vite preview", 20 | "publish": "npm run build" 21 | }, 22 | "devDependencies": { 23 | "rollup-plugin-cleanup": "^3.2.1", 24 | "typescript": "^5.3.3", 25 | "vite": "^5.1.1" 26 | } 27 | } -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | rollup-plugin-cleanup: 12 | specifier: ^3.2.1 13 | version: 3.2.1(rollup@4.18.0) 14 | typescript: 15 | specifier: ^5.3.3 16 | version: 5.4.5 17 | vite: 18 | specifier: ^5.1.1 19 | version: 5.2.12 20 | 21 | packages: 22 | 23 | '@esbuild/aix-ppc64@0.20.2': 24 | resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} 25 | engines: {node: '>=12'} 26 | cpu: [ppc64] 27 | os: [aix] 28 | 29 | '@esbuild/android-arm64@0.20.2': 30 | resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} 31 | engines: {node: '>=12'} 32 | cpu: [arm64] 33 | os: [android] 34 | 35 | '@esbuild/android-arm@0.20.2': 36 | resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} 37 | engines: {node: '>=12'} 38 | cpu: [arm] 39 | os: [android] 40 | 41 | '@esbuild/android-x64@0.20.2': 42 | resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} 43 | engines: {node: '>=12'} 44 | cpu: [x64] 45 | os: [android] 46 | 47 | '@esbuild/darwin-arm64@0.20.2': 48 | resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} 49 | engines: {node: '>=12'} 50 | cpu: [arm64] 51 | os: [darwin] 52 | 53 | '@esbuild/darwin-x64@0.20.2': 54 | resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} 55 | engines: {node: '>=12'} 56 | cpu: [x64] 57 | os: [darwin] 58 | 59 | '@esbuild/freebsd-arm64@0.20.2': 60 | resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} 61 | engines: {node: '>=12'} 62 | cpu: [arm64] 63 | os: [freebsd] 64 | 65 | '@esbuild/freebsd-x64@0.20.2': 66 | resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} 67 | engines: {node: '>=12'} 68 | cpu: [x64] 69 | os: [freebsd] 70 | 71 | '@esbuild/linux-arm64@0.20.2': 72 | resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} 73 | engines: {node: '>=12'} 74 | cpu: [arm64] 75 | os: [linux] 76 | 77 | '@esbuild/linux-arm@0.20.2': 78 | resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} 79 | engines: {node: '>=12'} 80 | cpu: [arm] 81 | os: [linux] 82 | 83 | '@esbuild/linux-ia32@0.20.2': 84 | resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} 85 | engines: {node: '>=12'} 86 | cpu: [ia32] 87 | os: [linux] 88 | 89 | '@esbuild/linux-loong64@0.20.2': 90 | resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} 91 | engines: {node: '>=12'} 92 | cpu: [loong64] 93 | os: [linux] 94 | 95 | '@esbuild/linux-mips64el@0.20.2': 96 | resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} 97 | engines: {node: '>=12'} 98 | cpu: [mips64el] 99 | os: [linux] 100 | 101 | '@esbuild/linux-ppc64@0.20.2': 102 | resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} 103 | engines: {node: '>=12'} 104 | cpu: [ppc64] 105 | os: [linux] 106 | 107 | '@esbuild/linux-riscv64@0.20.2': 108 | resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} 109 | engines: {node: '>=12'} 110 | cpu: [riscv64] 111 | os: [linux] 112 | 113 | '@esbuild/linux-s390x@0.20.2': 114 | resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} 115 | engines: {node: '>=12'} 116 | cpu: [s390x] 117 | os: [linux] 118 | 119 | '@esbuild/linux-x64@0.20.2': 120 | resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} 121 | engines: {node: '>=12'} 122 | cpu: [x64] 123 | os: [linux] 124 | 125 | '@esbuild/netbsd-x64@0.20.2': 126 | resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} 127 | engines: {node: '>=12'} 128 | cpu: [x64] 129 | os: [netbsd] 130 | 131 | '@esbuild/openbsd-x64@0.20.2': 132 | resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} 133 | engines: {node: '>=12'} 134 | cpu: [x64] 135 | os: [openbsd] 136 | 137 | '@esbuild/sunos-x64@0.20.2': 138 | resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} 139 | engines: {node: '>=12'} 140 | cpu: [x64] 141 | os: [sunos] 142 | 143 | '@esbuild/win32-arm64@0.20.2': 144 | resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} 145 | engines: {node: '>=12'} 146 | cpu: [arm64] 147 | os: [win32] 148 | 149 | '@esbuild/win32-ia32@0.20.2': 150 | resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} 151 | engines: {node: '>=12'} 152 | cpu: [ia32] 153 | os: [win32] 154 | 155 | '@esbuild/win32-x64@0.20.2': 156 | resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} 157 | engines: {node: '>=12'} 158 | cpu: [x64] 159 | os: [win32] 160 | 161 | '@rollup/rollup-android-arm-eabi@4.18.0': 162 | resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} 163 | cpu: [arm] 164 | os: [android] 165 | 166 | '@rollup/rollup-android-arm64@4.18.0': 167 | resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} 168 | cpu: [arm64] 169 | os: [android] 170 | 171 | '@rollup/rollup-darwin-arm64@4.18.0': 172 | resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} 173 | cpu: [arm64] 174 | os: [darwin] 175 | 176 | '@rollup/rollup-darwin-x64@4.18.0': 177 | resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} 178 | cpu: [x64] 179 | os: [darwin] 180 | 181 | '@rollup/rollup-linux-arm-gnueabihf@4.18.0': 182 | resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} 183 | cpu: [arm] 184 | os: [linux] 185 | 186 | '@rollup/rollup-linux-arm-musleabihf@4.18.0': 187 | resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} 188 | cpu: [arm] 189 | os: [linux] 190 | 191 | '@rollup/rollup-linux-arm64-gnu@4.18.0': 192 | resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} 193 | cpu: [arm64] 194 | os: [linux] 195 | 196 | '@rollup/rollup-linux-arm64-musl@4.18.0': 197 | resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} 198 | cpu: [arm64] 199 | os: [linux] 200 | 201 | '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': 202 | resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} 203 | cpu: [ppc64] 204 | os: [linux] 205 | 206 | '@rollup/rollup-linux-riscv64-gnu@4.18.0': 207 | resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} 208 | cpu: [riscv64] 209 | os: [linux] 210 | 211 | '@rollup/rollup-linux-s390x-gnu@4.18.0': 212 | resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} 213 | cpu: [s390x] 214 | os: [linux] 215 | 216 | '@rollup/rollup-linux-x64-gnu@4.18.0': 217 | resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} 218 | cpu: [x64] 219 | os: [linux] 220 | 221 | '@rollup/rollup-linux-x64-musl@4.18.0': 222 | resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} 223 | cpu: [x64] 224 | os: [linux] 225 | 226 | '@rollup/rollup-win32-arm64-msvc@4.18.0': 227 | resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} 228 | cpu: [arm64] 229 | os: [win32] 230 | 231 | '@rollup/rollup-win32-ia32-msvc@4.18.0': 232 | resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} 233 | cpu: [ia32] 234 | os: [win32] 235 | 236 | '@rollup/rollup-win32-x64-msvc@4.18.0': 237 | resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} 238 | cpu: [x64] 239 | os: [win32] 240 | 241 | '@types/estree@1.0.5': 242 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} 243 | 244 | esbuild@0.20.2: 245 | resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} 246 | engines: {node: '>=12'} 247 | hasBin: true 248 | 249 | estree-walker@0.6.1: 250 | resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} 251 | 252 | fsevents@2.3.3: 253 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 254 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 255 | os: [darwin] 256 | 257 | js-cleanup@1.2.0: 258 | resolution: {integrity: sha512-JeDD0yiiSt80fXzAVa/crrS0JDPQljyBG/RpOtaSbyDq03VHa9szJWMaWOYU/bcTn412uMN2MxApXq8v79cUiQ==} 259 | engines: {node: ^10.14.2 || >=12.0.0} 260 | 261 | magic-string@0.25.9: 262 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} 263 | 264 | nanoid@3.3.7: 265 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 266 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 267 | hasBin: true 268 | 269 | perf-regexes@1.0.1: 270 | resolution: {integrity: sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==} 271 | engines: {node: '>=6.14'} 272 | 273 | picocolors@1.0.1: 274 | resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} 275 | 276 | postcss@8.4.38: 277 | resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} 278 | engines: {node: ^10 || ^12 || >=14} 279 | 280 | rollup-plugin-cleanup@3.2.1: 281 | resolution: {integrity: sha512-zuv8EhoO3TpnrU8MX8W7YxSbO4gmOR0ny06Lm3nkFfq0IVKdBUtHwhVzY1OAJyNCIAdLiyPnOrU0KnO0Fri1GQ==} 282 | engines: {node: ^10.14.2 || >=12.0.0} 283 | peerDependencies: 284 | rollup: '>=2.0' 285 | 286 | rollup-pluginutils@2.8.2: 287 | resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} 288 | 289 | rollup@4.18.0: 290 | resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} 291 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 292 | hasBin: true 293 | 294 | skip-regex@1.0.2: 295 | resolution: {integrity: sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==} 296 | engines: {node: '>=4.2'} 297 | 298 | source-map-js@1.2.0: 299 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} 300 | engines: {node: '>=0.10.0'} 301 | 302 | sourcemap-codec@1.4.8: 303 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 304 | deprecated: Please use @jridgewell/sourcemap-codec instead 305 | 306 | typescript@5.4.5: 307 | resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} 308 | engines: {node: '>=14.17'} 309 | hasBin: true 310 | 311 | vite@5.2.12: 312 | resolution: {integrity: sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==} 313 | engines: {node: ^18.0.0 || >=20.0.0} 314 | hasBin: true 315 | peerDependencies: 316 | '@types/node': ^18.0.0 || >=20.0.0 317 | less: '*' 318 | lightningcss: ^1.21.0 319 | sass: '*' 320 | stylus: '*' 321 | sugarss: '*' 322 | terser: ^5.4.0 323 | peerDependenciesMeta: 324 | '@types/node': 325 | optional: true 326 | less: 327 | optional: true 328 | lightningcss: 329 | optional: true 330 | sass: 331 | optional: true 332 | stylus: 333 | optional: true 334 | sugarss: 335 | optional: true 336 | terser: 337 | optional: true 338 | 339 | snapshots: 340 | 341 | '@esbuild/aix-ppc64@0.20.2': 342 | optional: true 343 | 344 | '@esbuild/android-arm64@0.20.2': 345 | optional: true 346 | 347 | '@esbuild/android-arm@0.20.2': 348 | optional: true 349 | 350 | '@esbuild/android-x64@0.20.2': 351 | optional: true 352 | 353 | '@esbuild/darwin-arm64@0.20.2': 354 | optional: true 355 | 356 | '@esbuild/darwin-x64@0.20.2': 357 | optional: true 358 | 359 | '@esbuild/freebsd-arm64@0.20.2': 360 | optional: true 361 | 362 | '@esbuild/freebsd-x64@0.20.2': 363 | optional: true 364 | 365 | '@esbuild/linux-arm64@0.20.2': 366 | optional: true 367 | 368 | '@esbuild/linux-arm@0.20.2': 369 | optional: true 370 | 371 | '@esbuild/linux-ia32@0.20.2': 372 | optional: true 373 | 374 | '@esbuild/linux-loong64@0.20.2': 375 | optional: true 376 | 377 | '@esbuild/linux-mips64el@0.20.2': 378 | optional: true 379 | 380 | '@esbuild/linux-ppc64@0.20.2': 381 | optional: true 382 | 383 | '@esbuild/linux-riscv64@0.20.2': 384 | optional: true 385 | 386 | '@esbuild/linux-s390x@0.20.2': 387 | optional: true 388 | 389 | '@esbuild/linux-x64@0.20.2': 390 | optional: true 391 | 392 | '@esbuild/netbsd-x64@0.20.2': 393 | optional: true 394 | 395 | '@esbuild/openbsd-x64@0.20.2': 396 | optional: true 397 | 398 | '@esbuild/sunos-x64@0.20.2': 399 | optional: true 400 | 401 | '@esbuild/win32-arm64@0.20.2': 402 | optional: true 403 | 404 | '@esbuild/win32-ia32@0.20.2': 405 | optional: true 406 | 407 | '@esbuild/win32-x64@0.20.2': 408 | optional: true 409 | 410 | '@rollup/rollup-android-arm-eabi@4.18.0': 411 | optional: true 412 | 413 | '@rollup/rollup-android-arm64@4.18.0': 414 | optional: true 415 | 416 | '@rollup/rollup-darwin-arm64@4.18.0': 417 | optional: true 418 | 419 | '@rollup/rollup-darwin-x64@4.18.0': 420 | optional: true 421 | 422 | '@rollup/rollup-linux-arm-gnueabihf@4.18.0': 423 | optional: true 424 | 425 | '@rollup/rollup-linux-arm-musleabihf@4.18.0': 426 | optional: true 427 | 428 | '@rollup/rollup-linux-arm64-gnu@4.18.0': 429 | optional: true 430 | 431 | '@rollup/rollup-linux-arm64-musl@4.18.0': 432 | optional: true 433 | 434 | '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': 435 | optional: true 436 | 437 | '@rollup/rollup-linux-riscv64-gnu@4.18.0': 438 | optional: true 439 | 440 | '@rollup/rollup-linux-s390x-gnu@4.18.0': 441 | optional: true 442 | 443 | '@rollup/rollup-linux-x64-gnu@4.18.0': 444 | optional: true 445 | 446 | '@rollup/rollup-linux-x64-musl@4.18.0': 447 | optional: true 448 | 449 | '@rollup/rollup-win32-arm64-msvc@4.18.0': 450 | optional: true 451 | 452 | '@rollup/rollup-win32-ia32-msvc@4.18.0': 453 | optional: true 454 | 455 | '@rollup/rollup-win32-x64-msvc@4.18.0': 456 | optional: true 457 | 458 | '@types/estree@1.0.5': {} 459 | 460 | esbuild@0.20.2: 461 | optionalDependencies: 462 | '@esbuild/aix-ppc64': 0.20.2 463 | '@esbuild/android-arm': 0.20.2 464 | '@esbuild/android-arm64': 0.20.2 465 | '@esbuild/android-x64': 0.20.2 466 | '@esbuild/darwin-arm64': 0.20.2 467 | '@esbuild/darwin-x64': 0.20.2 468 | '@esbuild/freebsd-arm64': 0.20.2 469 | '@esbuild/freebsd-x64': 0.20.2 470 | '@esbuild/linux-arm': 0.20.2 471 | '@esbuild/linux-arm64': 0.20.2 472 | '@esbuild/linux-ia32': 0.20.2 473 | '@esbuild/linux-loong64': 0.20.2 474 | '@esbuild/linux-mips64el': 0.20.2 475 | '@esbuild/linux-ppc64': 0.20.2 476 | '@esbuild/linux-riscv64': 0.20.2 477 | '@esbuild/linux-s390x': 0.20.2 478 | '@esbuild/linux-x64': 0.20.2 479 | '@esbuild/netbsd-x64': 0.20.2 480 | '@esbuild/openbsd-x64': 0.20.2 481 | '@esbuild/sunos-x64': 0.20.2 482 | '@esbuild/win32-arm64': 0.20.2 483 | '@esbuild/win32-ia32': 0.20.2 484 | '@esbuild/win32-x64': 0.20.2 485 | 486 | estree-walker@0.6.1: {} 487 | 488 | fsevents@2.3.3: 489 | optional: true 490 | 491 | js-cleanup@1.2.0: 492 | dependencies: 493 | magic-string: 0.25.9 494 | perf-regexes: 1.0.1 495 | skip-regex: 1.0.2 496 | 497 | magic-string@0.25.9: 498 | dependencies: 499 | sourcemap-codec: 1.4.8 500 | 501 | nanoid@3.3.7: {} 502 | 503 | perf-regexes@1.0.1: {} 504 | 505 | picocolors@1.0.1: {} 506 | 507 | postcss@8.4.38: 508 | dependencies: 509 | nanoid: 3.3.7 510 | picocolors: 1.0.1 511 | source-map-js: 1.2.0 512 | 513 | rollup-plugin-cleanup@3.2.1(rollup@4.18.0): 514 | dependencies: 515 | js-cleanup: 1.2.0 516 | rollup: 4.18.0 517 | rollup-pluginutils: 2.8.2 518 | 519 | rollup-pluginutils@2.8.2: 520 | dependencies: 521 | estree-walker: 0.6.1 522 | 523 | rollup@4.18.0: 524 | dependencies: 525 | '@types/estree': 1.0.5 526 | optionalDependencies: 527 | '@rollup/rollup-android-arm-eabi': 4.18.0 528 | '@rollup/rollup-android-arm64': 4.18.0 529 | '@rollup/rollup-darwin-arm64': 4.18.0 530 | '@rollup/rollup-darwin-x64': 4.18.0 531 | '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 532 | '@rollup/rollup-linux-arm-musleabihf': 4.18.0 533 | '@rollup/rollup-linux-arm64-gnu': 4.18.0 534 | '@rollup/rollup-linux-arm64-musl': 4.18.0 535 | '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 536 | '@rollup/rollup-linux-riscv64-gnu': 4.18.0 537 | '@rollup/rollup-linux-s390x-gnu': 4.18.0 538 | '@rollup/rollup-linux-x64-gnu': 4.18.0 539 | '@rollup/rollup-linux-x64-musl': 4.18.0 540 | '@rollup/rollup-win32-arm64-msvc': 4.18.0 541 | '@rollup/rollup-win32-ia32-msvc': 4.18.0 542 | '@rollup/rollup-win32-x64-msvc': 4.18.0 543 | fsevents: 2.3.3 544 | 545 | skip-regex@1.0.2: {} 546 | 547 | source-map-js@1.2.0: {} 548 | 549 | sourcemap-codec@1.4.8: {} 550 | 551 | typescript@5.4.5: {} 552 | 553 | vite@5.2.12: 554 | dependencies: 555 | esbuild: 0.20.2 556 | postcss: 8.4.38 557 | rollup: 4.18.0 558 | optionalDependencies: 559 | fsevents: 2.3.3 560 | -------------------------------------------------------------------------------- /src/cue.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A valid VTT cue 3 | * 4 | * The properties of this class are compatible with `VTTCue` 5 | * and can be used to create a `new VTTCue` instance 6 | * 7 | * *Example* 8 | * ```js 9 | * new VTTCue(cue.startTime, cue.endTime, cue.text); 10 | * ``` 11 | * 12 | * @property {number} number 13 | * @property {number} startTime 14 | * @property {number} endTime 15 | * @property {string} text 16 | */ 17 | export default class Cue { 18 | /** 19 | * 20 | * @param {number} number 21 | * @param {number} startTime 22 | * @param {number} endTime 23 | * @param {string} text 24 | */ 25 | constructor(number: number, startTime: number, endTime: number, text: string); 26 | /** 27 | * @readonly 28 | * @type {number} 29 | */ 30 | readonly number: number; 31 | /** 32 | * @readonly 33 | * @type {number} 34 | */ 35 | readonly startTime: number; 36 | /** 37 | * @readonly 38 | * @type {number} 39 | */ 40 | readonly endTime: number; 41 | /** 42 | * @readonly 43 | * @type {string} 44 | */ 45 | readonly text: string; 46 | } 47 | -------------------------------------------------------------------------------- /src/cue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A valid VTT cue 3 | * 4 | * The properties of this class are compatible with `VTTCue` 5 | * and can be used to create a `new VTTCue` instance 6 | * 7 | * *Example* 8 | * ```js 9 | * new VTTCue(cue.startTime, cue.endTime, cue.text); 10 | * ``` 11 | * 12 | * @property {number} number 13 | * @property {number} startTime 14 | * @property {number} endTime 15 | * @property {string} text 16 | */ 17 | export default class Cue { 18 | /** 19 | * @readonly 20 | * @type {number} 21 | */ 22 | number; 23 | 24 | /** 25 | * @readonly 26 | * @type {number} 27 | */ 28 | startTime; 29 | 30 | /** 31 | * @readonly 32 | * @type {number} 33 | */ 34 | endTime; 35 | 36 | /** 37 | * @readonly 38 | * @type {string} 39 | */ 40 | text; 41 | 42 | /** 43 | * 44 | * @param {number} number 45 | * @param {number} startTime 46 | * @param {number} endTime 47 | * @param {string} text 48 | */ 49 | constructor(number, startTime, endTime, text) { 50 | this.number = number; 51 | this.startTime = startTime; 52 | this.endTime = endTime; 53 | this.text = text; 54 | } 55 | } -------------------------------------------------------------------------------- /src/helpers.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts an SRT cue into a VTT compatible cue 3 | * 4 | * For example 5 | * 6 | * ```txt 7 | * 1 8 | * 00:00:00,498 --> 00:00:02,827 9 | * Here's what I love most 10 | * about food and diet. 11 | * ``` 12 | * 13 | * Will be converted into 14 | * 15 | * ```js 16 | * Cue { 17 | * number: 1, 18 | * startTime: 0.498 19 | * endTime: 2.827, 20 | * text: 'Here\'s what I love most\n about food and diet.' 21 | * } 22 | * ``` 23 | * 24 | * @param {string} srtCue 25 | * @returns Cue 26 | */ 27 | export function toVttCue(srtCue: string): false | Cue; 28 | /** 29 | * Converts a VTT or SRT timing `string` 30 | * to a `number` in seconds + milliseconds 31 | * 32 | * *Example* 33 | * ```js 34 | * const seconds = hmsToSeconds('00:00:02.827'); // 2.827 35 | * ``` 36 | * 37 | * @param {string} str 38 | * @returns number 39 | */ 40 | export function hmsToSeconds(str: string): number; 41 | /** 42 | * Fetches the contents of a track source 43 | * 44 | * *Example* 45 | * ```js 46 | * const content = await fetchTrack('https://example.com/path/my-subtitle.srt') 47 | * ``` 48 | * @param {string} src - url 49 | * @param {string} encoding - file encoding format 50 | * @returns Promise 51 | */ 52 | export function fetchTrack(src: string, encoding?: string): Promise; 53 | /** 54 | * Converts SRT formatted string into a WebVTT formated string 55 | * 56 | * *Example* 57 | * 58 | * Converts 59 | * ```text 60 | * 1 61 | * 00:00:00,498 --> 00:00:02,827 62 | * - Here's what I love most 63 | * about food and diet. 64 | * 65 | * 2 66 | * 00:00:02,827 --> 00:00:06,383 67 | * We all eat several times a day, 68 | * and we're totally in charge 69 | * ``` 70 | * 71 | * Into 72 | * ```text 73 | * WEBVTT 74 | * 75 | * 1 76 | * 00:00:00.498 --> 00:00:02.827 77 | * - Here's what I love most 78 | * about food and diet. 79 | * 80 | * 2 81 | * 00:00:02.827 --> 00:00:06.383 82 | * We all eat several times a day, 83 | * and we're totally in charge 84 | * ``` 85 | * 86 | * @param {string} srtBody 87 | * @returns string 88 | */ 89 | export function srt2vtt(srtBody: string): string; 90 | import Cue from "./cue.js"; 91 | -------------------------------------------------------------------------------- /src/helpers.js: -------------------------------------------------------------------------------- 1 | import Cue from "./cue.js"; 2 | 3 | /** 4 | * Converts an SRT cue into a VTT compatible cue 5 | * 6 | * For example 7 | * 8 | * ```txt 9 | * 1 10 | * 00:00:00,498 --> 00:00:02,827 11 | * Here's what I love most 12 | * about food and diet. 13 | * ``` 14 | * 15 | * Will be converted into 16 | * 17 | * ```js 18 | * Cue { 19 | * number: 1, 20 | * startTime: 0.498 21 | * endTime: 2.827, 22 | * text: 'Here\'s what I love most\n about food and diet.' 23 | * } 24 | * ``` 25 | * 26 | * @param {string} srtCue 27 | * @returns Cue 28 | */ 29 | export function toVttCue(srtCue) { 30 | try { 31 | if( ! srtCue || srtCue === ' ' ) { 32 | return false; 33 | } 34 | 35 | const convertedCue = { 36 | number: parseInt(srtCue.match(/^\d+/g)[0]), 37 | timing: { 38 | start: srtCue.match(/(\d+:){2}\d+,\d+/g)[0].replace(',', '.'), 39 | end: srtCue.match(/(\d+:){2}\d+,\d+/g)[1].replace(',', '.') 40 | }, 41 | text: srtCue.split(/\r?\n/g).slice(2, srtCue.split(/\r?\n/g).length).join('\n') 42 | } 43 | 44 | return new Cue(convertedCue.number, hmsToSeconds(convertedCue.timing.start), hmsToSeconds(convertedCue.timing.end), convertedCue.text); 45 | } catch(e) { 46 | return false; 47 | } 48 | } 49 | /** 50 | * Converts a VTT or SRT timing `string` 51 | * to a `number` in seconds + milliseconds 52 | * 53 | * *Example* 54 | * ```js 55 | * const seconds = hmsToSeconds('00:00:02.827'); // 2.827 56 | * ``` 57 | * 58 | * @param {string} str 59 | * @returns number 60 | */ 61 | export function hmsToSeconds(str) { 62 | let p = str.split(':'), 63 | s = 0, 64 | m = 1; 65 | 66 | while (p.length > 0) { 67 | s += m * parseFloat(p.pop(), 10); 68 | m *= 60; 69 | } 70 | 71 | return s; 72 | } 73 | /** 74 | * Fetches the contents of a track source 75 | * 76 | * *Example* 77 | * ```js 78 | * const content = await fetchTrack('https://example.com/path/my-subtitle.srt') 79 | * ``` 80 | * @param {string} src - url 81 | * @param {string} encoding - file encoding format 82 | * @returns Promise 83 | */ 84 | export async function fetchTrack(src, encoding = 'utf-8') { 85 | if( ! encoding || encoding === '' ) { 86 | encoding = 'utf-8'; 87 | } 88 | 89 | return fetch(src).then(r => r.arrayBuffer()).then(r => new TextDecoder(encoding).decode(r)); 90 | } 91 | /** 92 | * Converts SRT formatted string into a WebVTT formated string 93 | * 94 | * *Example* 95 | * 96 | * Converts 97 | * ```text 98 | * 1 99 | * 00:00:00,498 --> 00:00:02,827 100 | * - Here's what I love most 101 | * about food and diet. 102 | * 103 | * 2 104 | * 00:00:02,827 --> 00:00:06,383 105 | * We all eat several times a day, 106 | * and we're totally in charge 107 | * ``` 108 | * 109 | * Into 110 | * ```text 111 | * WEBVTT 112 | * 113 | * 1 114 | * 00:00:00.498 --> 00:00:02.827 115 | * - Here's what I love most 116 | * about food and diet. 117 | * 118 | * 2 119 | * 00:00:02.827 --> 00:00:06.383 120 | * We all eat several times a day, 121 | * and we're totally in charge 122 | * ``` 123 | * 124 | * @param {string} srtBody 125 | * @returns string 126 | */ 127 | export function srt2vtt(srtBody) { 128 | return 'WEBVTT\n\n' + srtBody.split(/\n/g).map(line => line.replace(/((\d+:){0,2}\d+),(\d+)/g, '$1.$3')).join('\n'); 129 | } -------------------------------------------------------------------------------- /src/track.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @property {string} src 3 | * @property {string} encoding 4 | * @property {string} lang 5 | * @property {string} kind 6 | * @property {string} label 7 | * @property {string} default 8 | * @property {string} body 9 | * @property {boolean} needsTransform 10 | * @property {Cue[]} cues 11 | */ 12 | export default class Track { 13 | /** 14 | * Parses a `HTMLTrackElement` 15 | * 16 | * @param {HTMLTrackElement} track 17 | */ 18 | constructor(track: HTMLTrackElement); 19 | /** 20 | * @readonly 21 | * @type {HTMLTrackElement} 22 | */ 23 | readonly element: HTMLTrackElement; 24 | /** 25 | * @readonly 26 | * @type {string} 27 | */ 28 | readonly src: string; 29 | /** 30 | * @readonly 31 | * @type {string} 32 | */ 33 | readonly encoding: string; 34 | /** 35 | * @readonly 36 | * @type {string} 37 | */ 38 | readonly lang: string; 39 | /** 40 | * @readonly 41 | * @type {string} 42 | */ 43 | readonly kind: string; 44 | /** 45 | * @readonly 46 | * @type {string} 47 | */ 48 | readonly label: string; 49 | /** 50 | * @readonly 51 | * @type {boolean} 52 | */ 53 | readonly default: boolean; 54 | /** 55 | * @readonly 56 | * @type {string} 57 | */ 58 | readonly body: string; 59 | /** 60 | * @readonly 61 | * @type {boolean} 62 | */ 63 | readonly needsTransform: boolean; 64 | /** 65 | * @readonly 66 | * @type {Cue[]} 67 | */ 68 | readonly cues: Cue[]; 69 | parse(): Promise; 70 | } 71 | import Cue from './cue.js'; 72 | -------------------------------------------------------------------------------- /src/track.js: -------------------------------------------------------------------------------- 1 | import { toVttCue, fetchTrack } from './helpers.js'; 2 | import Cue from './cue.js'; 3 | 4 | /** 5 | * @property {string} src 6 | * @property {string} encoding 7 | * @property {string} lang 8 | * @property {string} kind 9 | * @property {string} label 10 | * @property {string} default 11 | * @property {string} body 12 | * @property {boolean} needsTransform 13 | * @property {Cue[]} cues 14 | */ 15 | export default class Track { 16 | /** 17 | * @readonly 18 | * @type {HTMLTrackElement} 19 | */ 20 | element; 21 | /** 22 | * @readonly 23 | * @type {string} 24 | */ 25 | src; 26 | /** 27 | * @readonly 28 | * @type {string} 29 | */ 30 | encoding; 31 | /** 32 | * @readonly 33 | * @type {string} 34 | */ 35 | lang; 36 | /** 37 | * @readonly 38 | * @type {string} 39 | */ 40 | kind; 41 | /** 42 | * @readonly 43 | * @type {string} 44 | */ 45 | label; 46 | /** 47 | * @readonly 48 | * @type {boolean} 49 | */ 50 | default; 51 | /** 52 | * @readonly 53 | * @type {string} 54 | */ 55 | body; 56 | /** 57 | * @readonly 58 | * @type {boolean} 59 | */ 60 | needsTransform; 61 | /** 62 | * @readonly 63 | * @type {Cue[]} 64 | */ 65 | cues = []; 66 | 67 | /** 68 | * Parses a `HTMLTrackElement` 69 | * 70 | * @param {HTMLTrackElement} track 71 | */ 72 | constructor(track) { 73 | this.element = track; 74 | this.src = track.src; 75 | this.encoding = track.dataset.encoding; 76 | this.lang = track.srclang; 77 | this.kind = track.kind; 78 | this.label = track.label; 79 | this.default = track.default; 80 | this.needsTransform = !this.src.toLowerCase().endsWith('.vtt'); 81 | } 82 | 83 | async parse() { 84 | this.body = await fetchTrack(this.src, this.encoding); 85 | this.cues = this.body.split(/\r?\n\r?\n/g).map(toVttCue).filter(Boolean); 86 | } 87 | } -------------------------------------------------------------------------------- /src/transformer.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts all SRT files into WebVTT files. 3 | * 4 | * @param {HTMLVideoElement} video 5 | */ 6 | export function transformSrtTracks(video: HTMLVideoElement): Promise; 7 | -------------------------------------------------------------------------------- /src/transformer.js: -------------------------------------------------------------------------------- 1 | import Track from './track.js'; 2 | 3 | /** 4 | * Converts all SRT files into WebVTT files. 5 | * 6 | * @param {HTMLVideoElement} video 7 | */ 8 | export async function transformSrtTracks(video) { 9 | const tracks = [...video.querySelectorAll('track')].map(track => new Track(track)); 10 | 11 | for (const track of tracks) { 12 | if ( ! track.needsTransform ) continue; 13 | /** 14 | * Fetch track from URL and parse its content 15 | * We need to do before we can use it. 16 | */ 17 | await track.parse(); 18 | 19 | /** 20 | * Remove the original 21 | */ 22 | track.element.remove(); 23 | 24 | /** 25 | * Add new TextTrack to video 26 | * We later fill this with the transformed data 27 | */ 28 | const t = video.addTextTrack(track.kind, track.label, track.lang); 29 | /** 30 | * Add all cue's we retrieved from the original 31 | * SRT file to the newly created track 32 | */ 33 | track.cues.forEach(cue => t.addCue(new VTTCue(cue.startTime, cue.endTime, cue.text))); 34 | 35 | if ( track.default ) { 36 | t.mode = 'showing'; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./main.js"], 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "declaration": true, 6 | "emitDeclarationOnly": true, 7 | "outDir": "dist", 8 | "declarationMap": true 9 | } 10 | } -------------------------------------------------------------------------------- /vite.config.esm.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | import { defineConfig } from 'vite' 3 | 4 | export default defineConfig({ 5 | build: { 6 | emptyOutDir: false, 7 | rollupOptions: { 8 | output: { 9 | entryFileNames: '[name].[format].js' 10 | } 11 | }, 12 | lib: { 13 | entry: 'main.js', 14 | name: 'SRT-Support-for-HTML5-videos', 15 | // the proper extensions will be added 16 | fileName: 'converter', 17 | formats: ['esm'] 18 | } 19 | } 20 | }) -------------------------------------------------------------------------------- /vite.config.iife.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | import { defineConfig } from 'vite' 3 | 4 | export default defineConfig({ 5 | build: { 6 | emptyOutDir: false, 7 | target: 'esnext', 8 | rollupOptions: { 9 | output: { 10 | entryFileNames: 'main.[format].js' 11 | } 12 | }, 13 | lib: { 14 | entry: 'browser.js', 15 | name: 'srt2vtt', 16 | // the proper extensions will be added 17 | fileName: 'main', 18 | formats: ['iife'] 19 | } 20 | } 21 | }) -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | import { defineConfig } from 'vite' 3 | import cleanup from 'rollup-plugin-cleanup'; 4 | 5 | export default defineConfig({ 6 | build: { 7 | emptyOutDir: false, 8 | minify: false, 9 | target: 'esnext', 10 | rollupOptions: { 11 | output: { 12 | entryFileNames: 'source.[format].js' 13 | }, 14 | plugins: [ 15 | cleanup({ 16 | comments: 'all' 17 | }) 18 | ] 19 | }, 20 | lib: { 21 | entry: 'browser.js', 22 | name: 'srt2vtt', 23 | // the proper extensions will be added 24 | fileName: 'main', 25 | formats: ['es'] 26 | } 27 | } 28 | }) --------------------------------------------------------------------------------