├── .changeset
├── README.md
└── config.json
├── .github
├── dependabot.yml
└── workflows
│ ├── main.yml
│ └── publish.yml
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── pnpm-lock.yaml
├── rollup.config.js
├── src
├── ass.ts
├── renderer.ts
├── types.ts
└── utils.ts
├── tsconfig.json
└── tsup.config.ts
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
3 | "changelog": "@changesets/cli/changelog",
4 | "commit": false,
5 | "fixed": [],
6 | "linked": [],
7 | "access": "public",
8 | "baseBranch": "main",
9 | "updateInternalDependencies": "patch",
10 | "ignore": []
11 | }
12 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: 'npm'
9 | directory: '/' # root
10 | schedule:
11 | interval: 'weekly'
12 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | branches:
5 | - '**'
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v3
12 | - uses: pnpm/action-setup@v2
13 | with:
14 | version: latest
15 | - uses: actions/setup-node@v3
16 | with:
17 | node-version: 18.x
18 | cache: 'pnpm'
19 |
20 | - run: pnpm install --frozen-lockfile
21 | - run: pnpm run build
22 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 | on:
3 | workflow_run:
4 | workflows: ['CI']
5 | types:
6 | - completed
7 | push:
8 | branches:
9 | - 'main'
10 |
11 | concurrency: ${{ github.workflow }}-${{ github.ref }}
12 |
13 | jobs:
14 | publish:
15 | if: ${{ github.event.workflow_run.conclusion == 'success' }}
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v3
19 | - uses: pnpm/action-setup@v2
20 | with:
21 | version: latest
22 | - uses: actions/setup-node@v3
23 | with:
24 | node-version: 18.x
25 | cache: 'pnpm'
26 |
27 | - run: pnpm install --frozen-lockfile
28 | - name: Create Release Pull Request or Publish
29 | id: changesets
30 | uses: changesets/action@v1
31 | with:
32 | publish: pnpm run release
33 | env:
34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .changeset
2 | pnpm-lock.yaml
3 | tsconfig.json
4 | tsup.config.ts
5 | CHANGELOG.md
6 | .github
7 | src
8 | .prettierignore
9 | .prettierrc
10 | README.md
11 | rollup.config.js
12 | .gitmodules
13 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | /.changeset
5 |
6 | # Ignore files for PNPM, NPM and YARN
7 | pnpm-lock.yaml
8 | package-lock.json
9 | yarn.lock
10 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "singleQuote": true,
6 | "trailingComma": "none",
7 | "printWidth": 100
8 | }
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ass-html5
2 |
3 | ## 0.5.3
4 |
5 | ### Patch Changes
6 |
7 | - b1053bf: [fix] single character color alternating not displayed
8 |
9 | ## 0.5.2
10 |
11 | ### Patch Changes
12 |
13 | - a325cfb: Custom animation support
14 |
15 | ## 0.5.1
16 |
17 | ### Patch Changes
18 |
19 | - 309ba25: NEW: Move Animation implemented
20 |
21 | BREAKING: Changing `LOGTYPE` from an emun to a bar simple type
22 |
23 | ## 0.5.0
24 |
25 | ### Minor Changes
26 |
27 | - 5d95b6a: Ass engine renderer rewrite
28 |
29 | ## 0.4.1
30 |
31 | ### Patch Changes
32 |
33 | - 90a8f29: removing `tsup` from dependencies
34 |
35 | ## 0.4.0
36 |
37 | ### Minor Changes
38 |
39 | - 3197954: Rendering encapsulation
40 |
41 | ## 0.3.6
42 |
43 | ### Patch Changes
44 |
45 | - 9e978ab: Adding text transparency
46 |
47 | ## 0.3.5
48 |
49 | ### Patch Changes
50 |
51 | - 8c59a89: Font vertical spacing & Text custom position improve
52 |
53 | ## 0.3.4
54 |
55 | ### Patch Changes
56 |
57 | - 0bdde5c: Custom Font Loading crash fixed
58 |
59 | ## 0.3.3
60 |
61 | ### Patch Changes
62 |
63 | - a45de93: - Font Vertical and Horizontal Transformation Support
64 |
65 | - Re-writing Core Part (Simplify)
66 |
67 | ## 0.3.2
68 |
69 | ### Patch Changes
70 |
71 | - 6278551: Uptade Modules to `mjs`, Fix import issues with cjs
72 |
73 | ## 0.3.1
74 |
75 | ### Patch Changes
76 |
77 | - 6ee8ac2: Lower the target es
78 |
79 | ## 0.3.0
80 |
81 | ### Minor Changes
82 |
83 | - 65d5e18: Adding custom fonts + Some bugs fixes
84 |
85 | ## 0.2.7
86 |
87 | ### Patch Changes
88 |
89 | - 53bbd52: Fix inline texts, correct tweaks tags application to font descriptor + Drawing text at a custom position improved
90 |
91 | ## 0.2.6
92 |
93 | ### Patch Changes
94 |
95 | - ea26665: Fix empty lines drawing
96 |
97 | ## 0.2.5
98 |
99 | ### Patch Changes
100 |
101 | - 5e1cb30: v0.2.5
102 |
103 | ## 0.2.4
104 |
105 | ### Patch Changes
106 |
107 | - 6dfddb2: Build for Web
108 |
109 | ## 0.2.4
110 |
111 | ### Patch Changes
112 |
113 | - a2719bb: Bug fixes in styled multilines (New way to draw text)
114 |
115 | ## 0.2.3
116 |
117 | ### Patch Changes
118 |
119 | - fc82eb5: Minor bug fixes
120 |
121 | ## 0.2.2
122 |
123 | ### Patch Changes
124 |
125 | - a51ae35: - Inline Changes in normal text display fix (with this bug, an inline transformation on a text while result in an overlapping on other drawn text)
126 | - Mutilines Texts Tweaks fix (End of Line Shifts)
127 |
128 | ## 0.2.1
129 |
130 | ### Patch Changes
131 |
132 | - fe65d34: Adding Inline Multi-Styling
133 |
134 | ## 0.2.0
135 |
136 | ### Minor Changes
137 |
138 | - 8a05416: Making `ass-compiler` (https://github.com/weizhenye/ass-compiler) internal. Using only the parse method
139 |
140 | ## 0.1.0
141 |
142 | ### Minor Changes
143 |
144 | - f0a1538: Adding Some Tweaks
145 |
146 | ## 0.0.1
147 |
148 | ### Patch Changes
149 |
150 | - cc7c0e1: Basic futures added
151 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-present luxluth
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 |
2 |
3 | # ass-html5
4 |
5 | Display ASS/SSA subtitles on html5 videos
6 |
7 | 
8 | 
9 | 
10 | 
11 | 
12 |
13 |
14 |
15 | ## Table of Contents
16 |
17 | - [ass-html5](#ass-html5)
18 | - [Table of Contents](#table-of-contents)
19 | - [Installation](#installation)
20 | - [Usage](#usage)
21 | - [Options](#options)
22 | - [Simple HTML](#simple-html)
23 | - [Svelte and Plry](#svelte-and-plry)
24 | - [videojs](#videojs)
25 | - [Credits](#credits)
26 |
27 | ## Installation
28 |
29 | ```bash
30 | pnpm add ass-html5
31 | ```
32 |
33 | ## Usage
34 |
35 | ### Options
36 |
37 | | option | description | required | type | default |
38 | | :-----: | :---------------------------------------------------------------------------------------------------------: | :------: | :---------------------------: | :-------------------: |
39 | | assText | The ass text string | ✅ | `string` | `undefined` |
40 | | video | The video to display the subtile on. Can be either an `HTMLVideoElement` or `string` (html query selector ) | ✅ | `HTMLVideoElement` / `string` | `undefined` |
41 | | fonts | Custom fonts to load | 🚫 | [`Font[]`](src/ass.ts#L72) | `undefined` |
42 | | zIndex | zIndex of the rendering frame | 🚫 | `number` | Drawn after the video |
43 | | onReady | A Callback that is invoked when the preprocess of the ass text by render is done | 🚫 | `() => void` | `undefined` |
44 | | logging | Type of logging (experimental) | 🚫 | [`LOGTYPE`](src/ass.ts#L44) | `LOGTYPE.DISABLE` |
45 |
46 | ### Simple HTML
47 |
48 | > [!NOTE]
49 | > The simple `video` tag element, in fullscreen mode, the position of the video is absolutely on top of any element.
50 | > No other element can go on top of it.
51 | >
52 | > It's therefore recommended to use a third party player rather than the native one. You can see an example with [plry](https://github.com/sampotts/plyr) [here](#svelte-and-plry).
53 |
54 | ```html
55 |
56 | ```
57 |
58 | ```html
59 |
60 | ```
61 |
62 | ```html
63 |
75 | ```
76 |
77 | ### [Svelte](https://github.com/sveltejs/svelte) and [Plry](https://github.com/sampotts/plyr)
78 |
79 | ```svelte
80 |
100 |
101 |
102 |
103 |
112 |
113 | ```
114 |
115 | ### [videojs](https://github.com/videojs/video.js)
116 |
117 | In the `head` :
118 |
119 | ```html
120 |
121 |
122 |
123 | ```
124 |
125 | In the `body` :
126 |
127 | ```html
128 |
137 |
138 |
139 | ```
140 |
141 | In the `script` tag :
142 |
143 | ```html
144 |
162 | ```
163 |
164 | ---
165 |
166 | # Credits
167 |
168 | Thanks to the [ass-compiler](https://github.com/weizhenye/ass-compiler/) by weizhenye.
169 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ass-html5",
3 | "version": "0.5.3",
4 | "description": "Display ASS/SSA subtitles on html5 videos",
5 | "main": "dist/ass.js",
6 | "module": "dist/ass.mjs",
7 | "types": "dist/ass.d.ts",
8 | "browser": "dist/ass.min.js",
9 | "scripts": {
10 | "build": "pnpm lint && pnpm run build:normal && pnpm run build:minify",
11 | "build:normal": "tsup",
12 | "build:minify": "rollup -c --bundleConfigAsCjs",
13 | "dev": "tsup --watch",
14 | "release": "pnpm run build && changeset publish",
15 | "lint": "tsc",
16 | "format": "prettier --write ."
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/luxluth/ass-html5.git"
21 | },
22 | "keywords": [
23 | "ASS",
24 | "SSA",
25 | "subtitles",
26 | "aegisub",
27 | "libass"
28 | ],
29 | "author": "luxluth",
30 | "license": "MIT",
31 | "bugs": {
32 | "url": "https://github.com/luxluth/ass-html5/issues"
33 | },
34 | "homepage": "https://github.com/luxluth/ass-html5#readme",
35 | "devDependencies": {
36 | "@changesets/cli": "^2.27.12",
37 | "@rollup/plugin-commonjs": "^28.0.2",
38 | "@rollup/plugin-node-resolve": "^16.0.0",
39 | "@rollup/plugin-terser": "^0.4.4",
40 | "@rollup/plugin-typescript": "^12.1.2",
41 | "@types/node": "^22.13.0",
42 | "ass-compiler": "^0.1.15",
43 | "prettier": "^3.4.2",
44 | "rollup": "^4.34.1",
45 | "terser": "^5.37.0",
46 | "tslib": "^2.8.1",
47 | "tsup": "^8.3.6",
48 | "typescript": "^5.7.3"
49 | },
50 | "pnpm": {
51 | "onlyBuiltDependencies": [
52 | "esbuild"
53 | ]
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | devDependencies:
11 | '@changesets/cli':
12 | specifier: ^2.27.12
13 | version: 2.28.1
14 | '@rollup/plugin-commonjs':
15 | specifier: ^28.0.2
16 | version: 28.0.2(rollup@4.34.8)
17 | '@rollup/plugin-node-resolve':
18 | specifier: ^16.0.0
19 | version: 16.0.0(rollup@4.34.8)
20 | '@rollup/plugin-terser':
21 | specifier: ^0.4.4
22 | version: 0.4.4(rollup@4.34.8)
23 | '@rollup/plugin-typescript':
24 | specifier: ^12.1.2
25 | version: 12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3)
26 | '@types/node':
27 | specifier: ^22.13.0
28 | version: 22.13.5
29 | ass-compiler:
30 | specifier: ^0.1.15
31 | version: 0.1.15
32 | prettier:
33 | specifier: ^3.4.2
34 | version: 3.5.2
35 | rollup:
36 | specifier: ^4.34.1
37 | version: 4.34.8
38 | terser:
39 | specifier: ^5.37.0
40 | version: 5.39.0
41 | tslib:
42 | specifier: ^2.8.1
43 | version: 2.8.1
44 | tsup:
45 | specifier: ^8.3.6
46 | version: 8.3.6(typescript@5.7.3)(yaml@2.4.2)
47 | typescript:
48 | specifier: ^5.7.3
49 | version: 5.7.3
50 |
51 | packages:
52 |
53 | '@babel/runtime@7.26.9':
54 | resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==}
55 | engines: {node: '>=6.9.0'}
56 |
57 | '@changesets/apply-release-plan@7.0.10':
58 | resolution: {integrity: sha512-wNyeIJ3yDsVspYvHnEz1xQDq18D9ifed3lI+wxRQRK4pArUcuHgCTrHv0QRnnwjhVCQACxZ+CBih3wgOct6UXw==}
59 |
60 | '@changesets/assemble-release-plan@6.0.6':
61 | resolution: {integrity: sha512-Frkj8hWJ1FRZiY3kzVCKzS0N5mMwWKwmv9vpam7vt8rZjLL1JMthdh6pSDVSPumHPshTTkKZ0VtNbE0cJHZZUg==}
62 |
63 | '@changesets/changelog-git@0.2.1':
64 | resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==}
65 |
66 | '@changesets/cli@2.28.1':
67 | resolution: {integrity: sha512-PiIyGRmSc6JddQJe/W1hRPjiN4VrMvb2VfQ6Uydy2punBioQrsxppyG5WafinKcW1mT0jOe/wU4k9Zy5ff21AA==}
68 | hasBin: true
69 |
70 | '@changesets/config@3.1.1':
71 | resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==}
72 |
73 | '@changesets/errors@0.2.0':
74 | resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==}
75 |
76 | '@changesets/get-dependents-graph@2.1.3':
77 | resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==}
78 |
79 | '@changesets/get-release-plan@4.0.8':
80 | resolution: {integrity: sha512-MM4mq2+DQU1ZT7nqxnpveDMTkMBLnwNX44cX7NSxlXmr7f8hO6/S2MXNiXG54uf/0nYnefv0cfy4Czf/ZL/EKQ==}
81 |
82 | '@changesets/get-version-range-type@0.4.0':
83 | resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==}
84 |
85 | '@changesets/git@3.0.2':
86 | resolution: {integrity: sha512-r1/Kju9Y8OxRRdvna+nxpQIsMsRQn9dhhAZt94FLDeu0Hij2hnOozW8iqnHBgvu+KdnJppCveQwK4odwfw/aWQ==}
87 |
88 | '@changesets/logger@0.1.1':
89 | resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==}
90 |
91 | '@changesets/parse@0.4.1':
92 | resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==}
93 |
94 | '@changesets/pre@2.0.2':
95 | resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==}
96 |
97 | '@changesets/read@0.6.3':
98 | resolution: {integrity: sha512-9H4p/OuJ3jXEUTjaVGdQEhBdqoT2cO5Ts95JTFsQyawmKzpL8FnIeJSyhTDPW1MBRDnwZlHFEM9SpPwJDY5wIg==}
99 |
100 | '@changesets/should-skip-package@0.1.2':
101 | resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==}
102 |
103 | '@changesets/types@4.1.0':
104 | resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==}
105 |
106 | '@changesets/types@6.1.0':
107 | resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==}
108 |
109 | '@changesets/write@0.4.0':
110 | resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
111 |
112 | '@esbuild/aix-ppc64@0.24.2':
113 | resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
114 | engines: {node: '>=18'}
115 | cpu: [ppc64]
116 | os: [aix]
117 |
118 | '@esbuild/android-arm64@0.24.2':
119 | resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==}
120 | engines: {node: '>=18'}
121 | cpu: [arm64]
122 | os: [android]
123 |
124 | '@esbuild/android-arm@0.24.2':
125 | resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==}
126 | engines: {node: '>=18'}
127 | cpu: [arm]
128 | os: [android]
129 |
130 | '@esbuild/android-x64@0.24.2':
131 | resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==}
132 | engines: {node: '>=18'}
133 | cpu: [x64]
134 | os: [android]
135 |
136 | '@esbuild/darwin-arm64@0.24.2':
137 | resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==}
138 | engines: {node: '>=18'}
139 | cpu: [arm64]
140 | os: [darwin]
141 |
142 | '@esbuild/darwin-x64@0.24.2':
143 | resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==}
144 | engines: {node: '>=18'}
145 | cpu: [x64]
146 | os: [darwin]
147 |
148 | '@esbuild/freebsd-arm64@0.24.2':
149 | resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==}
150 | engines: {node: '>=18'}
151 | cpu: [arm64]
152 | os: [freebsd]
153 |
154 | '@esbuild/freebsd-x64@0.24.2':
155 | resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==}
156 | engines: {node: '>=18'}
157 | cpu: [x64]
158 | os: [freebsd]
159 |
160 | '@esbuild/linux-arm64@0.24.2':
161 | resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==}
162 | engines: {node: '>=18'}
163 | cpu: [arm64]
164 | os: [linux]
165 |
166 | '@esbuild/linux-arm@0.24.2':
167 | resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==}
168 | engines: {node: '>=18'}
169 | cpu: [arm]
170 | os: [linux]
171 |
172 | '@esbuild/linux-ia32@0.24.2':
173 | resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==}
174 | engines: {node: '>=18'}
175 | cpu: [ia32]
176 | os: [linux]
177 |
178 | '@esbuild/linux-loong64@0.24.2':
179 | resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==}
180 | engines: {node: '>=18'}
181 | cpu: [loong64]
182 | os: [linux]
183 |
184 | '@esbuild/linux-mips64el@0.24.2':
185 | resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==}
186 | engines: {node: '>=18'}
187 | cpu: [mips64el]
188 | os: [linux]
189 |
190 | '@esbuild/linux-ppc64@0.24.2':
191 | resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==}
192 | engines: {node: '>=18'}
193 | cpu: [ppc64]
194 | os: [linux]
195 |
196 | '@esbuild/linux-riscv64@0.24.2':
197 | resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==}
198 | engines: {node: '>=18'}
199 | cpu: [riscv64]
200 | os: [linux]
201 |
202 | '@esbuild/linux-s390x@0.24.2':
203 | resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==}
204 | engines: {node: '>=18'}
205 | cpu: [s390x]
206 | os: [linux]
207 |
208 | '@esbuild/linux-x64@0.24.2':
209 | resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==}
210 | engines: {node: '>=18'}
211 | cpu: [x64]
212 | os: [linux]
213 |
214 | '@esbuild/netbsd-arm64@0.24.2':
215 | resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==}
216 | engines: {node: '>=18'}
217 | cpu: [arm64]
218 | os: [netbsd]
219 |
220 | '@esbuild/netbsd-x64@0.24.2':
221 | resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==}
222 | engines: {node: '>=18'}
223 | cpu: [x64]
224 | os: [netbsd]
225 |
226 | '@esbuild/openbsd-arm64@0.24.2':
227 | resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==}
228 | engines: {node: '>=18'}
229 | cpu: [arm64]
230 | os: [openbsd]
231 |
232 | '@esbuild/openbsd-x64@0.24.2':
233 | resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==}
234 | engines: {node: '>=18'}
235 | cpu: [x64]
236 | os: [openbsd]
237 |
238 | '@esbuild/sunos-x64@0.24.2':
239 | resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==}
240 | engines: {node: '>=18'}
241 | cpu: [x64]
242 | os: [sunos]
243 |
244 | '@esbuild/win32-arm64@0.24.2':
245 | resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==}
246 | engines: {node: '>=18'}
247 | cpu: [arm64]
248 | os: [win32]
249 |
250 | '@esbuild/win32-ia32@0.24.2':
251 | resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==}
252 | engines: {node: '>=18'}
253 | cpu: [ia32]
254 | os: [win32]
255 |
256 | '@esbuild/win32-x64@0.24.2':
257 | resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==}
258 | engines: {node: '>=18'}
259 | cpu: [x64]
260 | os: [win32]
261 |
262 | '@isaacs/cliui@8.0.2':
263 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
264 | engines: {node: '>=12'}
265 |
266 | '@jridgewell/gen-mapping@0.3.8':
267 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
268 | engines: {node: '>=6.0.0'}
269 |
270 | '@jridgewell/resolve-uri@3.1.2':
271 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
272 | engines: {node: '>=6.0.0'}
273 |
274 | '@jridgewell/set-array@1.2.1':
275 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
276 | engines: {node: '>=6.0.0'}
277 |
278 | '@jridgewell/source-map@0.3.6':
279 | resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==}
280 |
281 | '@jridgewell/sourcemap-codec@1.5.0':
282 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
283 |
284 | '@jridgewell/trace-mapping@0.3.25':
285 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
286 |
287 | '@manypkg/find-root@1.1.0':
288 | resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
289 |
290 | '@manypkg/get-packages@1.1.3':
291 | resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
292 |
293 | '@nodelib/fs.scandir@2.1.5':
294 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
295 | engines: {node: '>= 8'}
296 |
297 | '@nodelib/fs.stat@2.0.5':
298 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
299 | engines: {node: '>= 8'}
300 |
301 | '@nodelib/fs.walk@1.2.8':
302 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
303 | engines: {node: '>= 8'}
304 |
305 | '@pkgjs/parseargs@0.11.0':
306 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
307 | engines: {node: '>=14'}
308 |
309 | '@rollup/plugin-commonjs@28.0.2':
310 | resolution: {integrity: sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==}
311 | engines: {node: '>=16.0.0 || 14 >= 14.17'}
312 | peerDependencies:
313 | rollup: ^2.68.0||^3.0.0||^4.0.0
314 | peerDependenciesMeta:
315 | rollup:
316 | optional: true
317 |
318 | '@rollup/plugin-node-resolve@16.0.0':
319 | resolution: {integrity: sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==}
320 | engines: {node: '>=14.0.0'}
321 | peerDependencies:
322 | rollup: ^2.78.0||^3.0.0||^4.0.0
323 | peerDependenciesMeta:
324 | rollup:
325 | optional: true
326 |
327 | '@rollup/plugin-terser@0.4.4':
328 | resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==}
329 | engines: {node: '>=14.0.0'}
330 | peerDependencies:
331 | rollup: ^2.0.0||^3.0.0||^4.0.0
332 | peerDependenciesMeta:
333 | rollup:
334 | optional: true
335 |
336 | '@rollup/plugin-typescript@12.1.2':
337 | resolution: {integrity: sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==}
338 | engines: {node: '>=14.0.0'}
339 | peerDependencies:
340 | rollup: ^2.14.0||^3.0.0||^4.0.0
341 | tslib: '*'
342 | typescript: '>=3.7.0'
343 | peerDependenciesMeta:
344 | rollup:
345 | optional: true
346 | tslib:
347 | optional: true
348 |
349 | '@rollup/pluginutils@5.1.4':
350 | resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
351 | engines: {node: '>=14.0.0'}
352 | peerDependencies:
353 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
354 | peerDependenciesMeta:
355 | rollup:
356 | optional: true
357 |
358 | '@rollup/rollup-android-arm-eabi@4.34.8':
359 | resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==}
360 | cpu: [arm]
361 | os: [android]
362 |
363 | '@rollup/rollup-android-arm64@4.34.8':
364 | resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==}
365 | cpu: [arm64]
366 | os: [android]
367 |
368 | '@rollup/rollup-darwin-arm64@4.34.8':
369 | resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==}
370 | cpu: [arm64]
371 | os: [darwin]
372 |
373 | '@rollup/rollup-darwin-x64@4.34.8':
374 | resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==}
375 | cpu: [x64]
376 | os: [darwin]
377 |
378 | '@rollup/rollup-freebsd-arm64@4.34.8':
379 | resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==}
380 | cpu: [arm64]
381 | os: [freebsd]
382 |
383 | '@rollup/rollup-freebsd-x64@4.34.8':
384 | resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==}
385 | cpu: [x64]
386 | os: [freebsd]
387 |
388 | '@rollup/rollup-linux-arm-gnueabihf@4.34.8':
389 | resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==}
390 | cpu: [arm]
391 | os: [linux]
392 |
393 | '@rollup/rollup-linux-arm-musleabihf@4.34.8':
394 | resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==}
395 | cpu: [arm]
396 | os: [linux]
397 |
398 | '@rollup/rollup-linux-arm64-gnu@4.34.8':
399 | resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==}
400 | cpu: [arm64]
401 | os: [linux]
402 |
403 | '@rollup/rollup-linux-arm64-musl@4.34.8':
404 | resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==}
405 | cpu: [arm64]
406 | os: [linux]
407 |
408 | '@rollup/rollup-linux-loongarch64-gnu@4.34.8':
409 | resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==}
410 | cpu: [loong64]
411 | os: [linux]
412 |
413 | '@rollup/rollup-linux-powerpc64le-gnu@4.34.8':
414 | resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==}
415 | cpu: [ppc64]
416 | os: [linux]
417 |
418 | '@rollup/rollup-linux-riscv64-gnu@4.34.8':
419 | resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==}
420 | cpu: [riscv64]
421 | os: [linux]
422 |
423 | '@rollup/rollup-linux-s390x-gnu@4.34.8':
424 | resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==}
425 | cpu: [s390x]
426 | os: [linux]
427 |
428 | '@rollup/rollup-linux-x64-gnu@4.34.8':
429 | resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==}
430 | cpu: [x64]
431 | os: [linux]
432 |
433 | '@rollup/rollup-linux-x64-musl@4.34.8':
434 | resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==}
435 | cpu: [x64]
436 | os: [linux]
437 |
438 | '@rollup/rollup-win32-arm64-msvc@4.34.8':
439 | resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==}
440 | cpu: [arm64]
441 | os: [win32]
442 |
443 | '@rollup/rollup-win32-ia32-msvc@4.34.8':
444 | resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==}
445 | cpu: [ia32]
446 | os: [win32]
447 |
448 | '@rollup/rollup-win32-x64-msvc@4.34.8':
449 | resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==}
450 | cpu: [x64]
451 | os: [win32]
452 |
453 | '@types/estree@1.0.6':
454 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
455 |
456 | '@types/node@12.20.55':
457 | resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
458 |
459 | '@types/node@22.13.5':
460 | resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==}
461 |
462 | '@types/resolve@1.20.2':
463 | resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
464 |
465 | acorn@8.14.0:
466 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
467 | engines: {node: '>=0.4.0'}
468 | hasBin: true
469 |
470 | ansi-colors@4.1.3:
471 | resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
472 | engines: {node: '>=6'}
473 |
474 | ansi-regex@5.0.1:
475 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
476 | engines: {node: '>=8'}
477 |
478 | ansi-regex@6.1.0:
479 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
480 | engines: {node: '>=12'}
481 |
482 | ansi-styles@4.3.0:
483 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
484 | engines: {node: '>=8'}
485 |
486 | ansi-styles@6.2.1:
487 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
488 | engines: {node: '>=12'}
489 |
490 | any-promise@1.3.0:
491 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
492 |
493 | argparse@1.0.10:
494 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
495 |
496 | array-union@2.1.0:
497 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
498 | engines: {node: '>=8'}
499 |
500 | ass-compiler@0.1.15:
501 | resolution: {integrity: sha512-NPbNjCawqK/MKt1+0v5xezVxV2qk4AKIdl6tM3BsUohWQFb46WJaC0wJzMXlyGZbBJxx/AqKj3nalMSl+JZ+Jw==}
502 |
503 | balanced-match@1.0.2:
504 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
505 |
506 | better-path-resolve@1.0.0:
507 | resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
508 | engines: {node: '>=4'}
509 |
510 | brace-expansion@2.0.1:
511 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
512 |
513 | braces@3.0.3:
514 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
515 | engines: {node: '>=8'}
516 |
517 | buffer-from@1.1.2:
518 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
519 |
520 | bundle-require@5.1.0:
521 | resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
522 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
523 | peerDependencies:
524 | esbuild: '>=0.18'
525 |
526 | cac@6.7.14:
527 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
528 | engines: {node: '>=8'}
529 |
530 | chardet@0.7.0:
531 | resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
532 |
533 | chokidar@4.0.3:
534 | resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
535 | engines: {node: '>= 14.16.0'}
536 |
537 | ci-info@3.9.0:
538 | resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
539 | engines: {node: '>=8'}
540 |
541 | color-convert@2.0.1:
542 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
543 | engines: {node: '>=7.0.0'}
544 |
545 | color-name@1.1.4:
546 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
547 |
548 | commander@2.20.3:
549 | resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
550 |
551 | commander@4.1.1:
552 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
553 | engines: {node: '>= 6'}
554 |
555 | commondir@1.0.1:
556 | resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
557 |
558 | consola@3.4.0:
559 | resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==}
560 | engines: {node: ^14.18.0 || >=16.10.0}
561 |
562 | cross-spawn@7.0.6:
563 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
564 | engines: {node: '>= 8'}
565 |
566 | debug@4.4.0:
567 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
568 | engines: {node: '>=6.0'}
569 | peerDependencies:
570 | supports-color: '*'
571 | peerDependenciesMeta:
572 | supports-color:
573 | optional: true
574 |
575 | deepmerge@4.3.1:
576 | resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
577 | engines: {node: '>=0.10.0'}
578 |
579 | detect-indent@6.1.0:
580 | resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
581 | engines: {node: '>=8'}
582 |
583 | dir-glob@3.0.1:
584 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
585 | engines: {node: '>=8'}
586 |
587 | eastasianwidth@0.2.0:
588 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
589 |
590 | emoji-regex@8.0.0:
591 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
592 |
593 | emoji-regex@9.2.2:
594 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
595 |
596 | enquirer@2.4.1:
597 | resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
598 | engines: {node: '>=8.6'}
599 |
600 | esbuild@0.24.2:
601 | resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==}
602 | engines: {node: '>=18'}
603 | hasBin: true
604 |
605 | esprima@4.0.1:
606 | resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
607 | engines: {node: '>=4'}
608 | hasBin: true
609 |
610 | estree-walker@2.0.2:
611 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
612 |
613 | extendable-error@0.1.7:
614 | resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
615 |
616 | external-editor@3.1.0:
617 | resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
618 | engines: {node: '>=4'}
619 |
620 | fast-glob@3.3.3:
621 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
622 | engines: {node: '>=8.6.0'}
623 |
624 | fastq@1.19.0:
625 | resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==}
626 |
627 | fdir@6.4.3:
628 | resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
629 | peerDependencies:
630 | picomatch: ^3 || ^4
631 | peerDependenciesMeta:
632 | picomatch:
633 | optional: true
634 |
635 | fill-range@7.1.1:
636 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
637 | engines: {node: '>=8'}
638 |
639 | find-up@4.1.0:
640 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
641 | engines: {node: '>=8'}
642 |
643 | foreground-child@3.3.0:
644 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
645 | engines: {node: '>=14'}
646 |
647 | fs-extra@7.0.1:
648 | resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
649 | engines: {node: '>=6 <7 || >=8'}
650 |
651 | fs-extra@8.1.0:
652 | resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
653 | engines: {node: '>=6 <7 || >=8'}
654 |
655 | fsevents@2.3.3:
656 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
657 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
658 | os: [darwin]
659 |
660 | function-bind@1.1.2:
661 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
662 |
663 | glob-parent@5.1.2:
664 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
665 | engines: {node: '>= 6'}
666 |
667 | glob@10.4.5:
668 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
669 | hasBin: true
670 |
671 | globby@11.1.0:
672 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
673 | engines: {node: '>=10'}
674 |
675 | graceful-fs@4.2.11:
676 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
677 |
678 | hasown@2.0.2:
679 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
680 | engines: {node: '>= 0.4'}
681 |
682 | human-id@4.1.1:
683 | resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==}
684 | hasBin: true
685 |
686 | iconv-lite@0.4.24:
687 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
688 | engines: {node: '>=0.10.0'}
689 |
690 | ignore@5.3.2:
691 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
692 | engines: {node: '>= 4'}
693 |
694 | is-core-module@2.16.1:
695 | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
696 | engines: {node: '>= 0.4'}
697 |
698 | is-extglob@2.1.1:
699 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
700 | engines: {node: '>=0.10.0'}
701 |
702 | is-fullwidth-code-point@3.0.0:
703 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
704 | engines: {node: '>=8'}
705 |
706 | is-glob@4.0.3:
707 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
708 | engines: {node: '>=0.10.0'}
709 |
710 | is-module@1.0.0:
711 | resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
712 |
713 | is-number@7.0.0:
714 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
715 | engines: {node: '>=0.12.0'}
716 |
717 | is-reference@1.2.1:
718 | resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
719 |
720 | is-subdir@1.2.0:
721 | resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
722 | engines: {node: '>=4'}
723 |
724 | is-windows@1.0.2:
725 | resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
726 | engines: {node: '>=0.10.0'}
727 |
728 | isexe@2.0.0:
729 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
730 |
731 | jackspeak@3.4.3:
732 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
733 |
734 | joycon@3.1.1:
735 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
736 | engines: {node: '>=10'}
737 |
738 | js-yaml@3.14.1:
739 | resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
740 | hasBin: true
741 |
742 | jsonfile@4.0.0:
743 | resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
744 |
745 | lilconfig@3.1.3:
746 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
747 | engines: {node: '>=14'}
748 |
749 | lines-and-columns@1.2.4:
750 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
751 |
752 | load-tsconfig@0.2.5:
753 | resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
754 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
755 |
756 | locate-path@5.0.0:
757 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
758 | engines: {node: '>=8'}
759 |
760 | lodash.sortby@4.7.0:
761 | resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
762 |
763 | lodash.startcase@4.4.0:
764 | resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==}
765 |
766 | lru-cache@10.4.3:
767 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
768 |
769 | magic-string@0.30.17:
770 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
771 |
772 | merge2@1.4.1:
773 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
774 | engines: {node: '>= 8'}
775 |
776 | micromatch@4.0.8:
777 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
778 | engines: {node: '>=8.6'}
779 |
780 | minimatch@9.0.5:
781 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
782 | engines: {node: '>=16 || 14 >=14.17'}
783 |
784 | minipass@7.1.2:
785 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
786 | engines: {node: '>=16 || 14 >=14.17'}
787 |
788 | mri@1.2.0:
789 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
790 | engines: {node: '>=4'}
791 |
792 | ms@2.1.3:
793 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
794 |
795 | mz@2.7.0:
796 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
797 |
798 | object-assign@4.1.1:
799 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
800 | engines: {node: '>=0.10.0'}
801 |
802 | os-tmpdir@1.0.2:
803 | resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
804 | engines: {node: '>=0.10.0'}
805 |
806 | outdent@0.5.0:
807 | resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
808 |
809 | p-filter@2.1.0:
810 | resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
811 | engines: {node: '>=8'}
812 |
813 | p-limit@2.3.0:
814 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
815 | engines: {node: '>=6'}
816 |
817 | p-locate@4.1.0:
818 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
819 | engines: {node: '>=8'}
820 |
821 | p-map@2.1.0:
822 | resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
823 | engines: {node: '>=6'}
824 |
825 | p-try@2.2.0:
826 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
827 | engines: {node: '>=6'}
828 |
829 | package-json-from-dist@1.0.1:
830 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
831 |
832 | package-manager-detector@0.2.9:
833 | resolution: {integrity: sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q==}
834 |
835 | path-exists@4.0.0:
836 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
837 | engines: {node: '>=8'}
838 |
839 | path-key@3.1.1:
840 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
841 | engines: {node: '>=8'}
842 |
843 | path-parse@1.0.7:
844 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
845 |
846 | path-scurry@1.11.1:
847 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
848 | engines: {node: '>=16 || 14 >=14.18'}
849 |
850 | path-type@4.0.0:
851 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
852 | engines: {node: '>=8'}
853 |
854 | picocolors@1.1.1:
855 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
856 |
857 | picomatch@2.3.1:
858 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
859 | engines: {node: '>=8.6'}
860 |
861 | picomatch@4.0.2:
862 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
863 | engines: {node: '>=12'}
864 |
865 | pify@4.0.1:
866 | resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
867 | engines: {node: '>=6'}
868 |
869 | pirates@4.0.6:
870 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
871 | engines: {node: '>= 6'}
872 |
873 | postcss-load-config@6.0.1:
874 | resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
875 | engines: {node: '>= 18'}
876 | peerDependencies:
877 | jiti: '>=1.21.0'
878 | postcss: '>=8.0.9'
879 | tsx: ^4.8.1
880 | yaml: ^2.4.2
881 | peerDependenciesMeta:
882 | jiti:
883 | optional: true
884 | postcss:
885 | optional: true
886 | tsx:
887 | optional: true
888 | yaml:
889 | optional: true
890 |
891 | prettier@2.8.8:
892 | resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
893 | engines: {node: '>=10.13.0'}
894 | hasBin: true
895 |
896 | prettier@3.5.2:
897 | resolution: {integrity: sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==}
898 | engines: {node: '>=14'}
899 | hasBin: true
900 |
901 | punycode@2.3.1:
902 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
903 | engines: {node: '>=6'}
904 |
905 | queue-microtask@1.2.3:
906 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
907 |
908 | randombytes@2.1.0:
909 | resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
910 |
911 | read-yaml-file@1.1.0:
912 | resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==}
913 | engines: {node: '>=6'}
914 |
915 | readdirp@4.1.1:
916 | resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==}
917 | engines: {node: '>= 14.18.0'}
918 |
919 | regenerator-runtime@0.14.1:
920 | resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
921 |
922 | resolve-from@5.0.0:
923 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
924 | engines: {node: '>=8'}
925 |
926 | resolve@1.22.10:
927 | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
928 | engines: {node: '>= 0.4'}
929 | hasBin: true
930 |
931 | reusify@1.0.4:
932 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
933 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
934 |
935 | rollup@4.34.8:
936 | resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==}
937 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
938 | hasBin: true
939 |
940 | run-parallel@1.2.0:
941 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
942 |
943 | safe-buffer@5.2.1:
944 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
945 |
946 | safer-buffer@2.1.2:
947 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
948 |
949 | semver@7.7.1:
950 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
951 | engines: {node: '>=10'}
952 | hasBin: true
953 |
954 | serialize-javascript@6.0.2:
955 | resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
956 |
957 | shebang-command@2.0.0:
958 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
959 | engines: {node: '>=8'}
960 |
961 | shebang-regex@3.0.0:
962 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
963 | engines: {node: '>=8'}
964 |
965 | signal-exit@4.1.0:
966 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
967 | engines: {node: '>=14'}
968 |
969 | slash@3.0.0:
970 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
971 | engines: {node: '>=8'}
972 |
973 | smob@1.5.0:
974 | resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==}
975 |
976 | source-map-support@0.5.21:
977 | resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
978 |
979 | source-map@0.6.1:
980 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
981 | engines: {node: '>=0.10.0'}
982 |
983 | source-map@0.8.0-beta.0:
984 | resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
985 | engines: {node: '>= 8'}
986 |
987 | spawndamnit@3.0.1:
988 | resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
989 |
990 | sprintf-js@1.0.3:
991 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
992 |
993 | string-width@4.2.3:
994 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
995 | engines: {node: '>=8'}
996 |
997 | string-width@5.1.2:
998 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
999 | engines: {node: '>=12'}
1000 |
1001 | strip-ansi@6.0.1:
1002 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
1003 | engines: {node: '>=8'}
1004 |
1005 | strip-ansi@7.1.0:
1006 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
1007 | engines: {node: '>=12'}
1008 |
1009 | strip-bom@3.0.0:
1010 | resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
1011 | engines: {node: '>=4'}
1012 |
1013 | sucrase@3.35.0:
1014 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
1015 | engines: {node: '>=16 || 14 >=14.17'}
1016 | hasBin: true
1017 |
1018 | supports-preserve-symlinks-flag@1.0.0:
1019 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
1020 | engines: {node: '>= 0.4'}
1021 |
1022 | term-size@2.2.1:
1023 | resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
1024 | engines: {node: '>=8'}
1025 |
1026 | terser@5.39.0:
1027 | resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==}
1028 | engines: {node: '>=10'}
1029 | hasBin: true
1030 |
1031 | thenify-all@1.6.0:
1032 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
1033 | engines: {node: '>=0.8'}
1034 |
1035 | thenify@3.3.1:
1036 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
1037 |
1038 | tinyexec@0.3.2:
1039 | resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
1040 |
1041 | tinyglobby@0.2.10:
1042 | resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==}
1043 | engines: {node: '>=12.0.0'}
1044 |
1045 | tmp@0.0.33:
1046 | resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
1047 | engines: {node: '>=0.6.0'}
1048 |
1049 | to-regex-range@5.0.1:
1050 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
1051 | engines: {node: '>=8.0'}
1052 |
1053 | tr46@1.0.1:
1054 | resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
1055 |
1056 | tree-kill@1.2.2:
1057 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
1058 | hasBin: true
1059 |
1060 | ts-interface-checker@0.1.13:
1061 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
1062 |
1063 | tslib@2.8.1:
1064 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
1065 |
1066 | tsup@8.3.6:
1067 | resolution: {integrity: sha512-XkVtlDV/58S9Ye0JxUUTcrQk4S+EqlOHKzg6Roa62rdjL1nGWNUstG0xgI4vanHdfIpjP448J8vlN0oK6XOJ5g==}
1068 | engines: {node: '>=18'}
1069 | hasBin: true
1070 | peerDependencies:
1071 | '@microsoft/api-extractor': ^7.36.0
1072 | '@swc/core': ^1
1073 | postcss: ^8.4.12
1074 | typescript: '>=4.5.0'
1075 | peerDependenciesMeta:
1076 | '@microsoft/api-extractor':
1077 | optional: true
1078 | '@swc/core':
1079 | optional: true
1080 | postcss:
1081 | optional: true
1082 | typescript:
1083 | optional: true
1084 |
1085 | typescript@5.7.3:
1086 | resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==}
1087 | engines: {node: '>=14.17'}
1088 | hasBin: true
1089 |
1090 | undici-types@6.20.0:
1091 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
1092 |
1093 | universalify@0.1.2:
1094 | resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
1095 | engines: {node: '>= 4.0.0'}
1096 |
1097 | webidl-conversions@4.0.2:
1098 | resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
1099 |
1100 | whatwg-url@7.1.0:
1101 | resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
1102 |
1103 | which@2.0.2:
1104 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1105 | engines: {node: '>= 8'}
1106 | hasBin: true
1107 |
1108 | wrap-ansi@7.0.0:
1109 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1110 | engines: {node: '>=10'}
1111 |
1112 | wrap-ansi@8.1.0:
1113 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
1114 | engines: {node: '>=12'}
1115 |
1116 | yaml@2.4.2:
1117 | resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==}
1118 | engines: {node: '>= 14'}
1119 | hasBin: true
1120 |
1121 | snapshots:
1122 |
1123 | '@babel/runtime@7.26.9':
1124 | dependencies:
1125 | regenerator-runtime: 0.14.1
1126 |
1127 | '@changesets/apply-release-plan@7.0.10':
1128 | dependencies:
1129 | '@changesets/config': 3.1.1
1130 | '@changesets/get-version-range-type': 0.4.0
1131 | '@changesets/git': 3.0.2
1132 | '@changesets/should-skip-package': 0.1.2
1133 | '@changesets/types': 6.1.0
1134 | '@manypkg/get-packages': 1.1.3
1135 | detect-indent: 6.1.0
1136 | fs-extra: 7.0.1
1137 | lodash.startcase: 4.4.0
1138 | outdent: 0.5.0
1139 | prettier: 2.8.8
1140 | resolve-from: 5.0.0
1141 | semver: 7.7.1
1142 |
1143 | '@changesets/assemble-release-plan@6.0.6':
1144 | dependencies:
1145 | '@changesets/errors': 0.2.0
1146 | '@changesets/get-dependents-graph': 2.1.3
1147 | '@changesets/should-skip-package': 0.1.2
1148 | '@changesets/types': 6.1.0
1149 | '@manypkg/get-packages': 1.1.3
1150 | semver: 7.7.1
1151 |
1152 | '@changesets/changelog-git@0.2.1':
1153 | dependencies:
1154 | '@changesets/types': 6.1.0
1155 |
1156 | '@changesets/cli@2.28.1':
1157 | dependencies:
1158 | '@changesets/apply-release-plan': 7.0.10
1159 | '@changesets/assemble-release-plan': 6.0.6
1160 | '@changesets/changelog-git': 0.2.1
1161 | '@changesets/config': 3.1.1
1162 | '@changesets/errors': 0.2.0
1163 | '@changesets/get-dependents-graph': 2.1.3
1164 | '@changesets/get-release-plan': 4.0.8
1165 | '@changesets/git': 3.0.2
1166 | '@changesets/logger': 0.1.1
1167 | '@changesets/pre': 2.0.2
1168 | '@changesets/read': 0.6.3
1169 | '@changesets/should-skip-package': 0.1.2
1170 | '@changesets/types': 6.1.0
1171 | '@changesets/write': 0.4.0
1172 | '@manypkg/get-packages': 1.1.3
1173 | ansi-colors: 4.1.3
1174 | ci-info: 3.9.0
1175 | enquirer: 2.4.1
1176 | external-editor: 3.1.0
1177 | fs-extra: 7.0.1
1178 | mri: 1.2.0
1179 | p-limit: 2.3.0
1180 | package-manager-detector: 0.2.9
1181 | picocolors: 1.1.1
1182 | resolve-from: 5.0.0
1183 | semver: 7.7.1
1184 | spawndamnit: 3.0.1
1185 | term-size: 2.2.1
1186 |
1187 | '@changesets/config@3.1.1':
1188 | dependencies:
1189 | '@changesets/errors': 0.2.0
1190 | '@changesets/get-dependents-graph': 2.1.3
1191 | '@changesets/logger': 0.1.1
1192 | '@changesets/types': 6.1.0
1193 | '@manypkg/get-packages': 1.1.3
1194 | fs-extra: 7.0.1
1195 | micromatch: 4.0.8
1196 |
1197 | '@changesets/errors@0.2.0':
1198 | dependencies:
1199 | extendable-error: 0.1.7
1200 |
1201 | '@changesets/get-dependents-graph@2.1.3':
1202 | dependencies:
1203 | '@changesets/types': 6.1.0
1204 | '@manypkg/get-packages': 1.1.3
1205 | picocolors: 1.1.1
1206 | semver: 7.7.1
1207 |
1208 | '@changesets/get-release-plan@4.0.8':
1209 | dependencies:
1210 | '@changesets/assemble-release-plan': 6.0.6
1211 | '@changesets/config': 3.1.1
1212 | '@changesets/pre': 2.0.2
1213 | '@changesets/read': 0.6.3
1214 | '@changesets/types': 6.1.0
1215 | '@manypkg/get-packages': 1.1.3
1216 |
1217 | '@changesets/get-version-range-type@0.4.0': {}
1218 |
1219 | '@changesets/git@3.0.2':
1220 | dependencies:
1221 | '@changesets/errors': 0.2.0
1222 | '@manypkg/get-packages': 1.1.3
1223 | is-subdir: 1.2.0
1224 | micromatch: 4.0.8
1225 | spawndamnit: 3.0.1
1226 |
1227 | '@changesets/logger@0.1.1':
1228 | dependencies:
1229 | picocolors: 1.1.1
1230 |
1231 | '@changesets/parse@0.4.1':
1232 | dependencies:
1233 | '@changesets/types': 6.1.0
1234 | js-yaml: 3.14.1
1235 |
1236 | '@changesets/pre@2.0.2':
1237 | dependencies:
1238 | '@changesets/errors': 0.2.0
1239 | '@changesets/types': 6.1.0
1240 | '@manypkg/get-packages': 1.1.3
1241 | fs-extra: 7.0.1
1242 |
1243 | '@changesets/read@0.6.3':
1244 | dependencies:
1245 | '@changesets/git': 3.0.2
1246 | '@changesets/logger': 0.1.1
1247 | '@changesets/parse': 0.4.1
1248 | '@changesets/types': 6.1.0
1249 | fs-extra: 7.0.1
1250 | p-filter: 2.1.0
1251 | picocolors: 1.1.1
1252 |
1253 | '@changesets/should-skip-package@0.1.2':
1254 | dependencies:
1255 | '@changesets/types': 6.1.0
1256 | '@manypkg/get-packages': 1.1.3
1257 |
1258 | '@changesets/types@4.1.0': {}
1259 |
1260 | '@changesets/types@6.1.0': {}
1261 |
1262 | '@changesets/write@0.4.0':
1263 | dependencies:
1264 | '@changesets/types': 6.1.0
1265 | fs-extra: 7.0.1
1266 | human-id: 4.1.1
1267 | prettier: 2.8.8
1268 |
1269 | '@esbuild/aix-ppc64@0.24.2':
1270 | optional: true
1271 |
1272 | '@esbuild/android-arm64@0.24.2':
1273 | optional: true
1274 |
1275 | '@esbuild/android-arm@0.24.2':
1276 | optional: true
1277 |
1278 | '@esbuild/android-x64@0.24.2':
1279 | optional: true
1280 |
1281 | '@esbuild/darwin-arm64@0.24.2':
1282 | optional: true
1283 |
1284 | '@esbuild/darwin-x64@0.24.2':
1285 | optional: true
1286 |
1287 | '@esbuild/freebsd-arm64@0.24.2':
1288 | optional: true
1289 |
1290 | '@esbuild/freebsd-x64@0.24.2':
1291 | optional: true
1292 |
1293 | '@esbuild/linux-arm64@0.24.2':
1294 | optional: true
1295 |
1296 | '@esbuild/linux-arm@0.24.2':
1297 | optional: true
1298 |
1299 | '@esbuild/linux-ia32@0.24.2':
1300 | optional: true
1301 |
1302 | '@esbuild/linux-loong64@0.24.2':
1303 | optional: true
1304 |
1305 | '@esbuild/linux-mips64el@0.24.2':
1306 | optional: true
1307 |
1308 | '@esbuild/linux-ppc64@0.24.2':
1309 | optional: true
1310 |
1311 | '@esbuild/linux-riscv64@0.24.2':
1312 | optional: true
1313 |
1314 | '@esbuild/linux-s390x@0.24.2':
1315 | optional: true
1316 |
1317 | '@esbuild/linux-x64@0.24.2':
1318 | optional: true
1319 |
1320 | '@esbuild/netbsd-arm64@0.24.2':
1321 | optional: true
1322 |
1323 | '@esbuild/netbsd-x64@0.24.2':
1324 | optional: true
1325 |
1326 | '@esbuild/openbsd-arm64@0.24.2':
1327 | optional: true
1328 |
1329 | '@esbuild/openbsd-x64@0.24.2':
1330 | optional: true
1331 |
1332 | '@esbuild/sunos-x64@0.24.2':
1333 | optional: true
1334 |
1335 | '@esbuild/win32-arm64@0.24.2':
1336 | optional: true
1337 |
1338 | '@esbuild/win32-ia32@0.24.2':
1339 | optional: true
1340 |
1341 | '@esbuild/win32-x64@0.24.2':
1342 | optional: true
1343 |
1344 | '@isaacs/cliui@8.0.2':
1345 | dependencies:
1346 | string-width: 5.1.2
1347 | string-width-cjs: string-width@4.2.3
1348 | strip-ansi: 7.1.0
1349 | strip-ansi-cjs: strip-ansi@6.0.1
1350 | wrap-ansi: 8.1.0
1351 | wrap-ansi-cjs: wrap-ansi@7.0.0
1352 |
1353 | '@jridgewell/gen-mapping@0.3.8':
1354 | dependencies:
1355 | '@jridgewell/set-array': 1.2.1
1356 | '@jridgewell/sourcemap-codec': 1.5.0
1357 | '@jridgewell/trace-mapping': 0.3.25
1358 |
1359 | '@jridgewell/resolve-uri@3.1.2': {}
1360 |
1361 | '@jridgewell/set-array@1.2.1': {}
1362 |
1363 | '@jridgewell/source-map@0.3.6':
1364 | dependencies:
1365 | '@jridgewell/gen-mapping': 0.3.8
1366 | '@jridgewell/trace-mapping': 0.3.25
1367 |
1368 | '@jridgewell/sourcemap-codec@1.5.0': {}
1369 |
1370 | '@jridgewell/trace-mapping@0.3.25':
1371 | dependencies:
1372 | '@jridgewell/resolve-uri': 3.1.2
1373 | '@jridgewell/sourcemap-codec': 1.5.0
1374 |
1375 | '@manypkg/find-root@1.1.0':
1376 | dependencies:
1377 | '@babel/runtime': 7.26.9
1378 | '@types/node': 12.20.55
1379 | find-up: 4.1.0
1380 | fs-extra: 8.1.0
1381 |
1382 | '@manypkg/get-packages@1.1.3':
1383 | dependencies:
1384 | '@babel/runtime': 7.26.9
1385 | '@changesets/types': 4.1.0
1386 | '@manypkg/find-root': 1.1.0
1387 | fs-extra: 8.1.0
1388 | globby: 11.1.0
1389 | read-yaml-file: 1.1.0
1390 |
1391 | '@nodelib/fs.scandir@2.1.5':
1392 | dependencies:
1393 | '@nodelib/fs.stat': 2.0.5
1394 | run-parallel: 1.2.0
1395 |
1396 | '@nodelib/fs.stat@2.0.5': {}
1397 |
1398 | '@nodelib/fs.walk@1.2.8':
1399 | dependencies:
1400 | '@nodelib/fs.scandir': 2.1.5
1401 | fastq: 1.19.0
1402 |
1403 | '@pkgjs/parseargs@0.11.0':
1404 | optional: true
1405 |
1406 | '@rollup/plugin-commonjs@28.0.2(rollup@4.34.8)':
1407 | dependencies:
1408 | '@rollup/pluginutils': 5.1.4(rollup@4.34.8)
1409 | commondir: 1.0.1
1410 | estree-walker: 2.0.2
1411 | fdir: 6.4.3(picomatch@4.0.2)
1412 | is-reference: 1.2.1
1413 | magic-string: 0.30.17
1414 | picomatch: 4.0.2
1415 | optionalDependencies:
1416 | rollup: 4.34.8
1417 |
1418 | '@rollup/plugin-node-resolve@16.0.0(rollup@4.34.8)':
1419 | dependencies:
1420 | '@rollup/pluginutils': 5.1.4(rollup@4.34.8)
1421 | '@types/resolve': 1.20.2
1422 | deepmerge: 4.3.1
1423 | is-module: 1.0.0
1424 | resolve: 1.22.10
1425 | optionalDependencies:
1426 | rollup: 4.34.8
1427 |
1428 | '@rollup/plugin-terser@0.4.4(rollup@4.34.8)':
1429 | dependencies:
1430 | serialize-javascript: 6.0.2
1431 | smob: 1.5.0
1432 | terser: 5.39.0
1433 | optionalDependencies:
1434 | rollup: 4.34.8
1435 |
1436 | '@rollup/plugin-typescript@12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3)':
1437 | dependencies:
1438 | '@rollup/pluginutils': 5.1.4(rollup@4.34.8)
1439 | resolve: 1.22.10
1440 | typescript: 5.7.3
1441 | optionalDependencies:
1442 | rollup: 4.34.8
1443 | tslib: 2.8.1
1444 |
1445 | '@rollup/pluginutils@5.1.4(rollup@4.34.8)':
1446 | dependencies:
1447 | '@types/estree': 1.0.6
1448 | estree-walker: 2.0.2
1449 | picomatch: 4.0.2
1450 | optionalDependencies:
1451 | rollup: 4.34.8
1452 |
1453 | '@rollup/rollup-android-arm-eabi@4.34.8':
1454 | optional: true
1455 |
1456 | '@rollup/rollup-android-arm64@4.34.8':
1457 | optional: true
1458 |
1459 | '@rollup/rollup-darwin-arm64@4.34.8':
1460 | optional: true
1461 |
1462 | '@rollup/rollup-darwin-x64@4.34.8':
1463 | optional: true
1464 |
1465 | '@rollup/rollup-freebsd-arm64@4.34.8':
1466 | optional: true
1467 |
1468 | '@rollup/rollup-freebsd-x64@4.34.8':
1469 | optional: true
1470 |
1471 | '@rollup/rollup-linux-arm-gnueabihf@4.34.8':
1472 | optional: true
1473 |
1474 | '@rollup/rollup-linux-arm-musleabihf@4.34.8':
1475 | optional: true
1476 |
1477 | '@rollup/rollup-linux-arm64-gnu@4.34.8':
1478 | optional: true
1479 |
1480 | '@rollup/rollup-linux-arm64-musl@4.34.8':
1481 | optional: true
1482 |
1483 | '@rollup/rollup-linux-loongarch64-gnu@4.34.8':
1484 | optional: true
1485 |
1486 | '@rollup/rollup-linux-powerpc64le-gnu@4.34.8':
1487 | optional: true
1488 |
1489 | '@rollup/rollup-linux-riscv64-gnu@4.34.8':
1490 | optional: true
1491 |
1492 | '@rollup/rollup-linux-s390x-gnu@4.34.8':
1493 | optional: true
1494 |
1495 | '@rollup/rollup-linux-x64-gnu@4.34.8':
1496 | optional: true
1497 |
1498 | '@rollup/rollup-linux-x64-musl@4.34.8':
1499 | optional: true
1500 |
1501 | '@rollup/rollup-win32-arm64-msvc@4.34.8':
1502 | optional: true
1503 |
1504 | '@rollup/rollup-win32-ia32-msvc@4.34.8':
1505 | optional: true
1506 |
1507 | '@rollup/rollup-win32-x64-msvc@4.34.8':
1508 | optional: true
1509 |
1510 | '@types/estree@1.0.6': {}
1511 |
1512 | '@types/node@12.20.55': {}
1513 |
1514 | '@types/node@22.13.5':
1515 | dependencies:
1516 | undici-types: 6.20.0
1517 |
1518 | '@types/resolve@1.20.2': {}
1519 |
1520 | acorn@8.14.0: {}
1521 |
1522 | ansi-colors@4.1.3: {}
1523 |
1524 | ansi-regex@5.0.1: {}
1525 |
1526 | ansi-regex@6.1.0: {}
1527 |
1528 | ansi-styles@4.3.0:
1529 | dependencies:
1530 | color-convert: 2.0.1
1531 |
1532 | ansi-styles@6.2.1: {}
1533 |
1534 | any-promise@1.3.0: {}
1535 |
1536 | argparse@1.0.10:
1537 | dependencies:
1538 | sprintf-js: 1.0.3
1539 |
1540 | array-union@2.1.0: {}
1541 |
1542 | ass-compiler@0.1.15: {}
1543 |
1544 | balanced-match@1.0.2: {}
1545 |
1546 | better-path-resolve@1.0.0:
1547 | dependencies:
1548 | is-windows: 1.0.2
1549 |
1550 | brace-expansion@2.0.1:
1551 | dependencies:
1552 | balanced-match: 1.0.2
1553 |
1554 | braces@3.0.3:
1555 | dependencies:
1556 | fill-range: 7.1.1
1557 |
1558 | buffer-from@1.1.2: {}
1559 |
1560 | bundle-require@5.1.0(esbuild@0.24.2):
1561 | dependencies:
1562 | esbuild: 0.24.2
1563 | load-tsconfig: 0.2.5
1564 |
1565 | cac@6.7.14: {}
1566 |
1567 | chardet@0.7.0: {}
1568 |
1569 | chokidar@4.0.3:
1570 | dependencies:
1571 | readdirp: 4.1.1
1572 |
1573 | ci-info@3.9.0: {}
1574 |
1575 | color-convert@2.0.1:
1576 | dependencies:
1577 | color-name: 1.1.4
1578 |
1579 | color-name@1.1.4: {}
1580 |
1581 | commander@2.20.3: {}
1582 |
1583 | commander@4.1.1: {}
1584 |
1585 | commondir@1.0.1: {}
1586 |
1587 | consola@3.4.0: {}
1588 |
1589 | cross-spawn@7.0.6:
1590 | dependencies:
1591 | path-key: 3.1.1
1592 | shebang-command: 2.0.0
1593 | which: 2.0.2
1594 |
1595 | debug@4.4.0:
1596 | dependencies:
1597 | ms: 2.1.3
1598 |
1599 | deepmerge@4.3.1: {}
1600 |
1601 | detect-indent@6.1.0: {}
1602 |
1603 | dir-glob@3.0.1:
1604 | dependencies:
1605 | path-type: 4.0.0
1606 |
1607 | eastasianwidth@0.2.0: {}
1608 |
1609 | emoji-regex@8.0.0: {}
1610 |
1611 | emoji-regex@9.2.2: {}
1612 |
1613 | enquirer@2.4.1:
1614 | dependencies:
1615 | ansi-colors: 4.1.3
1616 | strip-ansi: 6.0.1
1617 |
1618 | esbuild@0.24.2:
1619 | optionalDependencies:
1620 | '@esbuild/aix-ppc64': 0.24.2
1621 | '@esbuild/android-arm': 0.24.2
1622 | '@esbuild/android-arm64': 0.24.2
1623 | '@esbuild/android-x64': 0.24.2
1624 | '@esbuild/darwin-arm64': 0.24.2
1625 | '@esbuild/darwin-x64': 0.24.2
1626 | '@esbuild/freebsd-arm64': 0.24.2
1627 | '@esbuild/freebsd-x64': 0.24.2
1628 | '@esbuild/linux-arm': 0.24.2
1629 | '@esbuild/linux-arm64': 0.24.2
1630 | '@esbuild/linux-ia32': 0.24.2
1631 | '@esbuild/linux-loong64': 0.24.2
1632 | '@esbuild/linux-mips64el': 0.24.2
1633 | '@esbuild/linux-ppc64': 0.24.2
1634 | '@esbuild/linux-riscv64': 0.24.2
1635 | '@esbuild/linux-s390x': 0.24.2
1636 | '@esbuild/linux-x64': 0.24.2
1637 | '@esbuild/netbsd-arm64': 0.24.2
1638 | '@esbuild/netbsd-x64': 0.24.2
1639 | '@esbuild/openbsd-arm64': 0.24.2
1640 | '@esbuild/openbsd-x64': 0.24.2
1641 | '@esbuild/sunos-x64': 0.24.2
1642 | '@esbuild/win32-arm64': 0.24.2
1643 | '@esbuild/win32-ia32': 0.24.2
1644 | '@esbuild/win32-x64': 0.24.2
1645 |
1646 | esprima@4.0.1: {}
1647 |
1648 | estree-walker@2.0.2: {}
1649 |
1650 | extendable-error@0.1.7: {}
1651 |
1652 | external-editor@3.1.0:
1653 | dependencies:
1654 | chardet: 0.7.0
1655 | iconv-lite: 0.4.24
1656 | tmp: 0.0.33
1657 |
1658 | fast-glob@3.3.3:
1659 | dependencies:
1660 | '@nodelib/fs.stat': 2.0.5
1661 | '@nodelib/fs.walk': 1.2.8
1662 | glob-parent: 5.1.2
1663 | merge2: 1.4.1
1664 | micromatch: 4.0.8
1665 |
1666 | fastq@1.19.0:
1667 | dependencies:
1668 | reusify: 1.0.4
1669 |
1670 | fdir@6.4.3(picomatch@4.0.2):
1671 | optionalDependencies:
1672 | picomatch: 4.0.2
1673 |
1674 | fill-range@7.1.1:
1675 | dependencies:
1676 | to-regex-range: 5.0.1
1677 |
1678 | find-up@4.1.0:
1679 | dependencies:
1680 | locate-path: 5.0.0
1681 | path-exists: 4.0.0
1682 |
1683 | foreground-child@3.3.0:
1684 | dependencies:
1685 | cross-spawn: 7.0.6
1686 | signal-exit: 4.1.0
1687 |
1688 | fs-extra@7.0.1:
1689 | dependencies:
1690 | graceful-fs: 4.2.11
1691 | jsonfile: 4.0.0
1692 | universalify: 0.1.2
1693 |
1694 | fs-extra@8.1.0:
1695 | dependencies:
1696 | graceful-fs: 4.2.11
1697 | jsonfile: 4.0.0
1698 | universalify: 0.1.2
1699 |
1700 | fsevents@2.3.3:
1701 | optional: true
1702 |
1703 | function-bind@1.1.2: {}
1704 |
1705 | glob-parent@5.1.2:
1706 | dependencies:
1707 | is-glob: 4.0.3
1708 |
1709 | glob@10.4.5:
1710 | dependencies:
1711 | foreground-child: 3.3.0
1712 | jackspeak: 3.4.3
1713 | minimatch: 9.0.5
1714 | minipass: 7.1.2
1715 | package-json-from-dist: 1.0.1
1716 | path-scurry: 1.11.1
1717 |
1718 | globby@11.1.0:
1719 | dependencies:
1720 | array-union: 2.1.0
1721 | dir-glob: 3.0.1
1722 | fast-glob: 3.3.3
1723 | ignore: 5.3.2
1724 | merge2: 1.4.1
1725 | slash: 3.0.0
1726 |
1727 | graceful-fs@4.2.11: {}
1728 |
1729 | hasown@2.0.2:
1730 | dependencies:
1731 | function-bind: 1.1.2
1732 |
1733 | human-id@4.1.1: {}
1734 |
1735 | iconv-lite@0.4.24:
1736 | dependencies:
1737 | safer-buffer: 2.1.2
1738 |
1739 | ignore@5.3.2: {}
1740 |
1741 | is-core-module@2.16.1:
1742 | dependencies:
1743 | hasown: 2.0.2
1744 |
1745 | is-extglob@2.1.1: {}
1746 |
1747 | is-fullwidth-code-point@3.0.0: {}
1748 |
1749 | is-glob@4.0.3:
1750 | dependencies:
1751 | is-extglob: 2.1.1
1752 |
1753 | is-module@1.0.0: {}
1754 |
1755 | is-number@7.0.0: {}
1756 |
1757 | is-reference@1.2.1:
1758 | dependencies:
1759 | '@types/estree': 1.0.6
1760 |
1761 | is-subdir@1.2.0:
1762 | dependencies:
1763 | better-path-resolve: 1.0.0
1764 |
1765 | is-windows@1.0.2: {}
1766 |
1767 | isexe@2.0.0: {}
1768 |
1769 | jackspeak@3.4.3:
1770 | dependencies:
1771 | '@isaacs/cliui': 8.0.2
1772 | optionalDependencies:
1773 | '@pkgjs/parseargs': 0.11.0
1774 |
1775 | joycon@3.1.1: {}
1776 |
1777 | js-yaml@3.14.1:
1778 | dependencies:
1779 | argparse: 1.0.10
1780 | esprima: 4.0.1
1781 |
1782 | jsonfile@4.0.0:
1783 | optionalDependencies:
1784 | graceful-fs: 4.2.11
1785 |
1786 | lilconfig@3.1.3: {}
1787 |
1788 | lines-and-columns@1.2.4: {}
1789 |
1790 | load-tsconfig@0.2.5: {}
1791 |
1792 | locate-path@5.0.0:
1793 | dependencies:
1794 | p-locate: 4.1.0
1795 |
1796 | lodash.sortby@4.7.0: {}
1797 |
1798 | lodash.startcase@4.4.0: {}
1799 |
1800 | lru-cache@10.4.3: {}
1801 |
1802 | magic-string@0.30.17:
1803 | dependencies:
1804 | '@jridgewell/sourcemap-codec': 1.5.0
1805 |
1806 | merge2@1.4.1: {}
1807 |
1808 | micromatch@4.0.8:
1809 | dependencies:
1810 | braces: 3.0.3
1811 | picomatch: 2.3.1
1812 |
1813 | minimatch@9.0.5:
1814 | dependencies:
1815 | brace-expansion: 2.0.1
1816 |
1817 | minipass@7.1.2: {}
1818 |
1819 | mri@1.2.0: {}
1820 |
1821 | ms@2.1.3: {}
1822 |
1823 | mz@2.7.0:
1824 | dependencies:
1825 | any-promise: 1.3.0
1826 | object-assign: 4.1.1
1827 | thenify-all: 1.6.0
1828 |
1829 | object-assign@4.1.1: {}
1830 |
1831 | os-tmpdir@1.0.2: {}
1832 |
1833 | outdent@0.5.0: {}
1834 |
1835 | p-filter@2.1.0:
1836 | dependencies:
1837 | p-map: 2.1.0
1838 |
1839 | p-limit@2.3.0:
1840 | dependencies:
1841 | p-try: 2.2.0
1842 |
1843 | p-locate@4.1.0:
1844 | dependencies:
1845 | p-limit: 2.3.0
1846 |
1847 | p-map@2.1.0: {}
1848 |
1849 | p-try@2.2.0: {}
1850 |
1851 | package-json-from-dist@1.0.1: {}
1852 |
1853 | package-manager-detector@0.2.9: {}
1854 |
1855 | path-exists@4.0.0: {}
1856 |
1857 | path-key@3.1.1: {}
1858 |
1859 | path-parse@1.0.7: {}
1860 |
1861 | path-scurry@1.11.1:
1862 | dependencies:
1863 | lru-cache: 10.4.3
1864 | minipass: 7.1.2
1865 |
1866 | path-type@4.0.0: {}
1867 |
1868 | picocolors@1.1.1: {}
1869 |
1870 | picomatch@2.3.1: {}
1871 |
1872 | picomatch@4.0.2: {}
1873 |
1874 | pify@4.0.1: {}
1875 |
1876 | pirates@4.0.6: {}
1877 |
1878 | postcss-load-config@6.0.1(yaml@2.4.2):
1879 | dependencies:
1880 | lilconfig: 3.1.3
1881 | optionalDependencies:
1882 | yaml: 2.4.2
1883 |
1884 | prettier@2.8.8: {}
1885 |
1886 | prettier@3.5.2: {}
1887 |
1888 | punycode@2.3.1: {}
1889 |
1890 | queue-microtask@1.2.3: {}
1891 |
1892 | randombytes@2.1.0:
1893 | dependencies:
1894 | safe-buffer: 5.2.1
1895 |
1896 | read-yaml-file@1.1.0:
1897 | dependencies:
1898 | graceful-fs: 4.2.11
1899 | js-yaml: 3.14.1
1900 | pify: 4.0.1
1901 | strip-bom: 3.0.0
1902 |
1903 | readdirp@4.1.1: {}
1904 |
1905 | regenerator-runtime@0.14.1: {}
1906 |
1907 | resolve-from@5.0.0: {}
1908 |
1909 | resolve@1.22.10:
1910 | dependencies:
1911 | is-core-module: 2.16.1
1912 | path-parse: 1.0.7
1913 | supports-preserve-symlinks-flag: 1.0.0
1914 |
1915 | reusify@1.0.4: {}
1916 |
1917 | rollup@4.34.8:
1918 | dependencies:
1919 | '@types/estree': 1.0.6
1920 | optionalDependencies:
1921 | '@rollup/rollup-android-arm-eabi': 4.34.8
1922 | '@rollup/rollup-android-arm64': 4.34.8
1923 | '@rollup/rollup-darwin-arm64': 4.34.8
1924 | '@rollup/rollup-darwin-x64': 4.34.8
1925 | '@rollup/rollup-freebsd-arm64': 4.34.8
1926 | '@rollup/rollup-freebsd-x64': 4.34.8
1927 | '@rollup/rollup-linux-arm-gnueabihf': 4.34.8
1928 | '@rollup/rollup-linux-arm-musleabihf': 4.34.8
1929 | '@rollup/rollup-linux-arm64-gnu': 4.34.8
1930 | '@rollup/rollup-linux-arm64-musl': 4.34.8
1931 | '@rollup/rollup-linux-loongarch64-gnu': 4.34.8
1932 | '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8
1933 | '@rollup/rollup-linux-riscv64-gnu': 4.34.8
1934 | '@rollup/rollup-linux-s390x-gnu': 4.34.8
1935 | '@rollup/rollup-linux-x64-gnu': 4.34.8
1936 | '@rollup/rollup-linux-x64-musl': 4.34.8
1937 | '@rollup/rollup-win32-arm64-msvc': 4.34.8
1938 | '@rollup/rollup-win32-ia32-msvc': 4.34.8
1939 | '@rollup/rollup-win32-x64-msvc': 4.34.8
1940 | fsevents: 2.3.3
1941 |
1942 | run-parallel@1.2.0:
1943 | dependencies:
1944 | queue-microtask: 1.2.3
1945 |
1946 | safe-buffer@5.2.1: {}
1947 |
1948 | safer-buffer@2.1.2: {}
1949 |
1950 | semver@7.7.1: {}
1951 |
1952 | serialize-javascript@6.0.2:
1953 | dependencies:
1954 | randombytes: 2.1.0
1955 |
1956 | shebang-command@2.0.0:
1957 | dependencies:
1958 | shebang-regex: 3.0.0
1959 |
1960 | shebang-regex@3.0.0: {}
1961 |
1962 | signal-exit@4.1.0: {}
1963 |
1964 | slash@3.0.0: {}
1965 |
1966 | smob@1.5.0: {}
1967 |
1968 | source-map-support@0.5.21:
1969 | dependencies:
1970 | buffer-from: 1.1.2
1971 | source-map: 0.6.1
1972 |
1973 | source-map@0.6.1: {}
1974 |
1975 | source-map@0.8.0-beta.0:
1976 | dependencies:
1977 | whatwg-url: 7.1.0
1978 |
1979 | spawndamnit@3.0.1:
1980 | dependencies:
1981 | cross-spawn: 7.0.6
1982 | signal-exit: 4.1.0
1983 |
1984 | sprintf-js@1.0.3: {}
1985 |
1986 | string-width@4.2.3:
1987 | dependencies:
1988 | emoji-regex: 8.0.0
1989 | is-fullwidth-code-point: 3.0.0
1990 | strip-ansi: 6.0.1
1991 |
1992 | string-width@5.1.2:
1993 | dependencies:
1994 | eastasianwidth: 0.2.0
1995 | emoji-regex: 9.2.2
1996 | strip-ansi: 7.1.0
1997 |
1998 | strip-ansi@6.0.1:
1999 | dependencies:
2000 | ansi-regex: 5.0.1
2001 |
2002 | strip-ansi@7.1.0:
2003 | dependencies:
2004 | ansi-regex: 6.1.0
2005 |
2006 | strip-bom@3.0.0: {}
2007 |
2008 | sucrase@3.35.0:
2009 | dependencies:
2010 | '@jridgewell/gen-mapping': 0.3.8
2011 | commander: 4.1.1
2012 | glob: 10.4.5
2013 | lines-and-columns: 1.2.4
2014 | mz: 2.7.0
2015 | pirates: 4.0.6
2016 | ts-interface-checker: 0.1.13
2017 |
2018 | supports-preserve-symlinks-flag@1.0.0: {}
2019 |
2020 | term-size@2.2.1: {}
2021 |
2022 | terser@5.39.0:
2023 | dependencies:
2024 | '@jridgewell/source-map': 0.3.6
2025 | acorn: 8.14.0
2026 | commander: 2.20.3
2027 | source-map-support: 0.5.21
2028 |
2029 | thenify-all@1.6.0:
2030 | dependencies:
2031 | thenify: 3.3.1
2032 |
2033 | thenify@3.3.1:
2034 | dependencies:
2035 | any-promise: 1.3.0
2036 |
2037 | tinyexec@0.3.2: {}
2038 |
2039 | tinyglobby@0.2.10:
2040 | dependencies:
2041 | fdir: 6.4.3(picomatch@4.0.2)
2042 | picomatch: 4.0.2
2043 |
2044 | tmp@0.0.33:
2045 | dependencies:
2046 | os-tmpdir: 1.0.2
2047 |
2048 | to-regex-range@5.0.1:
2049 | dependencies:
2050 | is-number: 7.0.0
2051 |
2052 | tr46@1.0.1:
2053 | dependencies:
2054 | punycode: 2.3.1
2055 |
2056 | tree-kill@1.2.2: {}
2057 |
2058 | ts-interface-checker@0.1.13: {}
2059 |
2060 | tslib@2.8.1: {}
2061 |
2062 | tsup@8.3.6(typescript@5.7.3)(yaml@2.4.2):
2063 | dependencies:
2064 | bundle-require: 5.1.0(esbuild@0.24.2)
2065 | cac: 6.7.14
2066 | chokidar: 4.0.3
2067 | consola: 3.4.0
2068 | debug: 4.4.0
2069 | esbuild: 0.24.2
2070 | joycon: 3.1.1
2071 | picocolors: 1.1.1
2072 | postcss-load-config: 6.0.1(yaml@2.4.2)
2073 | resolve-from: 5.0.0
2074 | rollup: 4.34.8
2075 | source-map: 0.8.0-beta.0
2076 | sucrase: 3.35.0
2077 | tinyexec: 0.3.2
2078 | tinyglobby: 0.2.10
2079 | tree-kill: 1.2.2
2080 | optionalDependencies:
2081 | typescript: 5.7.3
2082 | transitivePeerDependencies:
2083 | - jiti
2084 | - supports-color
2085 | - tsx
2086 | - yaml
2087 |
2088 | typescript@5.7.3: {}
2089 |
2090 | undici-types@6.20.0: {}
2091 |
2092 | universalify@0.1.2: {}
2093 |
2094 | webidl-conversions@4.0.2: {}
2095 |
2096 | whatwg-url@7.1.0:
2097 | dependencies:
2098 | lodash.sortby: 4.7.0
2099 | tr46: 1.0.1
2100 | webidl-conversions: 4.0.2
2101 |
2102 | which@2.0.2:
2103 | dependencies:
2104 | isexe: 2.0.0
2105 |
2106 | wrap-ansi@7.0.0:
2107 | dependencies:
2108 | ansi-styles: 4.3.0
2109 | string-width: 4.2.3
2110 | strip-ansi: 6.0.1
2111 |
2112 | wrap-ansi@8.1.0:
2113 | dependencies:
2114 | ansi-styles: 6.2.1
2115 | string-width: 5.1.2
2116 | strip-ansi: 7.1.0
2117 |
2118 | yaml@2.4.2:
2119 | optional: true
2120 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from '@rollup/plugin-node-resolve';
2 | import commonjs from '@rollup/plugin-commonjs';
3 | import typescript from '@rollup/plugin-typescript';
4 | import terser from '@rollup/plugin-terser';
5 |
6 | export default {
7 | input: 'src/ass.ts',
8 | output: [
9 | {
10 | file: 'dist/ass.min.js',
11 | format: 'iife',
12 | name: 'ASS',
13 | exports: 'named'
14 | }
15 | ],
16 | plugins: [typescript(), resolve(), commonjs(), terser()]
17 | };
18 |
--------------------------------------------------------------------------------
/src/ass.ts:
--------------------------------------------------------------------------------
1 | import { compile, type CompiledASS } from 'ass-compiler';
2 | import { Renderer } from './renderer';
3 | import type { OnInitSizes } from './types';
4 |
5 | export type ASSOptions = {
6 | /**
7 | * The ass text
8 | */
9 | assText: string;
10 |
11 | /**
12 | * The video to display the subtile on.
13 | * Can be either an `HTMLVideoElement` or `string` (html query selector)
14 | */
15 | video: HTMLVideoElement | string;
16 |
17 | /**
18 | * List of fonts to load. This ensures that all the fonts
19 | * needed for the rendering are present and loaded into the document
20 | */
21 | fonts?: Font[];
22 |
23 | /**
24 | * Corresponds to the `z-index` to placed the Canvas renderer
25 | * > The renderer will always be added right after the `video` element
26 | */
27 | zIndex?: number;
28 |
29 | /**
30 | * A Callback that is invoked when the preprocess of the ass text by render is done
31 | */
32 | onReady?: () => void;
33 |
34 | /**
35 | * Type of logging
36 | * - `DEBUG` only debug type log will be displayed
37 | * - `DISABLE` no logging will be emitted (default)
38 | * - `VERBOSE` every log will be shown
39 | * - `WARN` only warning will be shown
40 | */
41 | logging?: LOGTYPE;
42 | };
43 |
44 | export type LOGTYPE = 'DISABLE' | 'VERBOSE' | 'DEBUG' | 'WARN';
45 |
46 | export type FontStyle = {
47 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/ascentOverride) */
48 | ascentOverride: string;
49 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/descentOverride) */
50 | descentOverride: string;
51 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/display) */
52 | display: FontDisplay;
53 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/family) */
54 | family: string;
55 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/featureSettings) */
56 | featureSettings: string;
57 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/lineGapOverride) */
58 | lineGapOverride: string;
59 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/stretch) */
60 | stretch: string;
61 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/style) */
62 | style: string;
63 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/unicodeRange) */
64 | unicodeRange: string;
65 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/variant) */
66 | variant: string;
67 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/weight) */
68 | weight: string;
69 | /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/FontFace/load) */
70 | };
71 |
72 | export type Font = {
73 | family: string;
74 | url: string;
75 | descriptors?: Partial;
76 | };
77 |
78 | /**
79 | * @class ASS
80 | *
81 | * ASS is an ass/ssa subtitle renderer.
82 | *
83 | * It uses a `canvas` that is placed on top of
84 | * the targeted video element
85 | * */
86 | export default class ASS {
87 | assText: string;
88 | private video: HTMLVideoElement | string;
89 | videoElement: HTMLVideoElement | null = null;
90 | private renderer: Renderer | null = null;
91 | private ro: ResizeObserver | null = null;
92 | private fonts?: Font[];
93 | private zIndex?: number;
94 | private onReady?: () => void;
95 | private logging: LOGTYPE = 'DISABLE';
96 | private compiledAss: CompiledASS;
97 |
98 | constructor(options: ASSOptions) {
99 | this.assText = options.assText;
100 | this.compiledAss = compile(this.assText, {});
101 | this.video = options.video;
102 | this.fonts = options.fonts;
103 | this.zIndex = options.zIndex;
104 | this.onReady = options.onReady;
105 | if (options.logging) this.logging = options.logging;
106 | }
107 |
108 | /**
109 | * Start the ass rendering process
110 | */
111 | async render() {
112 | if (typeof this.video == 'string') {
113 | this.videoElement = document.querySelector(this.video);
114 | if (this.videoElement === null) {
115 | throw new Error('Unable to find the video element');
116 | }
117 | } else {
118 | this.videoElement = this.video;
119 | }
120 |
121 | const sizes = this.setCanvasSize();
122 |
123 | if (typeof this.fonts !== 'undefined') {
124 | await this.loadFonts(this.fonts);
125 | }
126 |
127 | if (this.videoElement) {
128 | this.renderer = new Renderer(
129 | this.compiledAss,
130 | sizes,
131 | this.videoElement,
132 | this.logging,
133 | this.zIndex
134 | );
135 | this.setCanvasSize();
136 | this.videoElement.addEventListener('loadedmetadata', this.setCanvasSize.bind(this));
137 |
138 | this.ro = new ResizeObserver(this.setCanvasSize.bind(this));
139 | this.ro.observe(this.videoElement);
140 |
141 | await this.renderer.warmup();
142 | if (this.onReady) {
143 | this.onReady();
144 | }
145 |
146 | await this.renderer.startRendering();
147 | }
148 | }
149 |
150 | /**
151 | * Stop the rendering
152 | */
153 | destroy() {
154 | this.videoElement?.removeEventListener('loadedmetadata', this.setCanvasSize.bind(this));
155 | this.ro?.disconnect();
156 |
157 | this.renderer?.destroy();
158 | this.renderer = null;
159 | }
160 |
161 | private setCanvasSize() {
162 | const { videoWidth, videoHeight, offsetTop, offsetLeft } = this
163 | .videoElement as HTMLVideoElement;
164 | const aspectRatio = videoWidth / videoHeight;
165 |
166 | const maxWidth = this.videoElement?.clientWidth || 0;
167 | const maxHeight = this.videoElement?.clientHeight || 0;
168 |
169 | let width = maxWidth;
170 | let height = maxHeight;
171 | let x = offsetLeft;
172 | let y = offsetTop;
173 |
174 | if (maxHeight * aspectRatio > maxWidth) {
175 | width = maxWidth;
176 | height = width / aspectRatio;
177 | y += (maxHeight - height) / 2;
178 | } else {
179 | height = maxHeight;
180 | width = height * aspectRatio;
181 | x += (maxWidth - width) / 2;
182 | }
183 |
184 | const sizes = {
185 | width,
186 | height,
187 | x,
188 | y
189 | } as OnInitSizes;
190 |
191 | if (this.renderer?.renderDiv) {
192 | this.renderer.renderDiv.style.width = width + 'px';
193 | this.renderer.renderDiv.style.height = height + 'px';
194 | this.renderer.renderDiv.style.top = y + 'px';
195 | this.renderer.renderDiv.style.left = x + 'px';
196 | }
197 |
198 | this.renderer?.layers.forEach((layer) => {
199 | layer.canvas.width = width;
200 | layer.canvas.height = height;
201 | });
202 |
203 | return sizes;
204 | }
205 |
206 | private async loadFonts(fonts: Font[]) {
207 | for (const font of fonts) {
208 | try {
209 | const loaded = await this.loadFont(font);
210 | if (loaded) {
211 | if (this.logging == 'VERBOSE')
212 | console.info(`Font ${font.family} loaded from ${font.url}`);
213 | } else {
214 | if (this.logging == 'VERBOSE' || this.logging == 'WARN')
215 | console.warn(`Unable to load font ${font.family} from ${font.url}`);
216 | }
217 | } catch (e) {
218 | if (this.logging == 'VERBOSE' || this.logging == 'WARN') {
219 | console.warn(`Unable to load font ${font.family} from ${font.url}`);
220 | console.warn(e);
221 | }
222 | }
223 | }
224 | }
225 |
226 | private async getFontUrl(fontUrl: string) {
227 | const response = await fetch(fontUrl);
228 | const blob = await response.blob();
229 | return URL.createObjectURL(blob);
230 | }
231 |
232 | private async loadFont(font: Font) {
233 | const url = await this.getFontUrl(font.url);
234 | const fontFace = new FontFace(font.family, `url(${url})`, font.descriptors || {});
235 | const loadedFace = await fontFace.load();
236 | // @ts-ignore
237 | document.fonts.add(loadedFace);
238 | return fontFace.status === 'loaded';
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/renderer.ts:
--------------------------------------------------------------------------------
1 | import type { CompiledASS, CompiledASSStyle, Dialogue, DialogueSlice } from 'ass-compiler';
2 | import type { CompiledTag } from 'ass-compiler/types/tags';
3 |
4 | import type {
5 | StyleDescriptor,
6 | Styles,
7 | Position,
8 | OnInitSizes,
9 | Layer,
10 | Margin,
11 | Char,
12 | Word,
13 | FadeAnimation,
14 | CustomAnimation
15 | } from './types';
16 | import { CHARKIND, LOGTYPE, Align, Baseline, FadeKind } from './types';
17 | import {
18 | ruleOfThree,
19 | blendAlpha,
20 | convertAegisubColorToHex,
21 | swapBBGGRR,
22 | newCanvas,
23 | newRender,
24 | Vector2,
25 | stringHash,
26 | chunkCharWidth,
27 | chunkCharToString,
28 | vectorLerp,
29 | getOpacity,
30 | getOpacityComplex,
31 | lerp,
32 | parseAlpha
33 | } from './utils';
34 |
35 | type PreProceesedAss = {
36 | start: number;
37 | layer: number;
38 | end: number;
39 | style: string;
40 | margin: Margin;
41 | pos?: Position;
42 | move?: MoveAnimation;
43 | fade?: FadeAnimation;
44 | rotationOrigin?: Vector2;
45 | alignment: number;
46 | chars: Char[];
47 | };
48 |
49 | type MoveAnimation = {
50 | // x1: number;
51 | // y1: number;
52 | from: Vector2;
53 | // x2: number;
54 | //y2: number;
55 | to: Vector2;
56 | // t1: number;
57 | start: number;
58 | //t2: number;
59 | end: number;
60 | };
61 |
62 | export class Renderer {
63 | compiledASS: CompiledASS;
64 | renderDiv: HTMLDivElement;
65 | layers: Layer[];
66 | numberOfLayers: number;
67 | video: HTMLVideoElement;
68 | playerResX: number;
69 | playerResY: number;
70 | stop: boolean = false;
71 | animationHandle: number | null = null;
72 | _log: LOGTYPE;
73 | ppass: PreProceesedAss[] = [];
74 | styles: Styles;
75 | collisions: 'Normal' | 'Reverse' = 'Normal';
76 | dt = 0;
77 | previous = 0;
78 | currentTime = 0;
79 |
80 | constructor(
81 | ass: CompiledASS,
82 | sizes: OnInitSizes,
83 | video: HTMLVideoElement,
84 | log: LOGTYPE,
85 | zIndex?: number
86 | ) {
87 | this._log = log;
88 | this.compiledASS = ass;
89 | this.styles = ass.styles;
90 | this.collisions = ass.collisions;
91 | if (this._log === 'DEBUG') {
92 | this.log('DEBUG', this.compiledASS);
93 | }
94 | this.playerResX = this.compiledASS.width;
95 | this.playerResY = this.compiledASS.height;
96 | this.renderDiv = newRender(sizes.y, sizes.x, sizes.width, sizes.height, zIndex, video);
97 | const background = newCanvas(sizes.width, sizes.height, -1, 'background', this.renderDiv);
98 | const bgCtx = background.getContext('2d') as CanvasRenderingContext2D;
99 | if (bgCtx === null) {
100 | throw new Error('Unable to initilize the Canvas 2D context');
101 | }
102 | this.layers = [
103 | {
104 | canvas: background,
105 | ctx: bgCtx
106 | }
107 | ];
108 |
109 | this.numberOfLayers = this.findTotalLayers(ass);
110 | this.insertLayers(sizes, background);
111 | this.video = video;
112 | }
113 |
114 | insertLayers(sizes: OnInitSizes, insertAfter: HTMLCanvasElement) {
115 | for (let i = 0; i < this.numberOfLayers; i++) {
116 | const canvas = newCanvas(sizes.width, sizes.height, i, 'frame', undefined, insertAfter);
117 | const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
118 | if (ctx === null) {
119 | throw new Error('Unable to initilize the Canvas 2D context');
120 | }
121 |
122 | //@ts-ignore
123 | ctx.textRendering = 'geometricPrecision';
124 |
125 | this.layers.push({
126 | canvas: canvas,
127 | ctx: ctx
128 | });
129 | }
130 | }
131 |
132 | getLayer(l: number): Layer | null {
133 | for (let i = 1; i < this.layers.length; i++) {
134 | if (this.layers[i]?.canvas.dataset.layer == l.toString()) {
135 | return this.layers[i] as Layer;
136 | }
137 | }
138 | return null;
139 | }
140 |
141 | findTotalLayers(ass: CompiledASS) {
142 | let maxLayer = 1;
143 | ass.dialogues.forEach((dialogue) => {
144 | if (dialogue.layer >= maxLayer) maxLayer++;
145 | });
146 |
147 | return maxLayer;
148 | }
149 |
150 | async warmup() {
151 | const { dialogues } = this.compiledASS;
152 | const canvas = document.createElement('canvas');
153 | canvas.height = this.playerResY;
154 | canvas.width = this.playerResX;
155 | const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
156 | const computelayer: Layer = {
157 | ctx,
158 | canvas
159 | };
160 |
161 | computelayer.canvas.width = this.playerResX;
162 | computelayer.canvas.height = this.playerResY;
163 | console.debug(dialogues);
164 |
165 | for (let i = 0; i < dialogues.length; i++) {
166 | const dia = dialogues[i] as Dialogue;
167 | const { layer, alignment, start, end, style, margin, slices, pos, move, org, fade } = dia;
168 | let movAnim: MoveAnimation | undefined;
169 | let rotOrg: Vector2 | undefined;
170 | let fadeAnim: FadeAnimation | undefined;
171 |
172 | if (move) {
173 | movAnim = {
174 | from: new Vector2(move.x1, move.y1),
175 | to: new Vector2(move.x2, move.y2),
176 | start: move.t1,
177 | end: move.t2
178 | };
179 | }
180 |
181 | if (org) {
182 | rotOrg = new Vector2(org.x, org.y);
183 | }
184 |
185 | if (fade) {
186 | switch (fade.type) {
187 | case 'fad':
188 | fadeAnim = { type: FadeKind.Simple, fadein: fade.t1, fadeout: fade.t2 };
189 | break;
190 | case 'fade':
191 | let { a1, a2, a3, t1, t2, t3, t4 } = fade;
192 | fadeAnim = { type: FadeKind.Complex, a1, a2, a3, t1, t2, t3, t4 };
193 | break;
194 | }
195 | }
196 |
197 | this.ppass.push({
198 | start,
199 | layer,
200 | end,
201 | style,
202 | margin,
203 | alignment,
204 | pos,
205 | move: movAnim,
206 | fade: fadeAnim,
207 | rotationOrigin: rotOrg,
208 | chars: this.processSlices(alignment, slices, computelayer)
209 | });
210 | }
211 | }
212 |
213 | processSlices(alignment: number, slices: DialogueSlice[], layer: Layer): Char[] {
214 | let chars: Char[] = [];
215 | slices.forEach((slice) => {
216 | const { style, fragments } = slice;
217 | let font = this.computeStyle(style, alignment, layer);
218 |
219 | let _frag: Char[] = [];
220 |
221 | fragments.forEach((frag) => {
222 | this.applyOverrideTag(frag.tag, font);
223 | this.applyFont(font, layer);
224 |
225 | //@ts-ignore
226 | const text = frag.text.replaceAll('\\N', '\n').split('');
227 |
228 | let ord = 0;
229 | let chars: Char[] = [];
230 |
231 | for (let i = 0; i < text.length; i++) {
232 | const char = text[i] as string;
233 | if (char == '\n') {
234 | chars.push({
235 | kind: CHARKIND.NEWLINE
236 | });
237 | ord = 0;
238 | } else {
239 | chars.push({
240 | kind: CHARKIND.NORMAL,
241 | pos: new Vector2(),
242 | c: char,
243 | ord,
244 | w: 0,
245 | style,
246 | tag: frag.tag
247 | });
248 |
249 | ord += 1;
250 | }
251 | }
252 |
253 | _frag = _frag.concat(chars);
254 | });
255 |
256 | chars = chars.concat(_frag);
257 | });
258 |
259 | return chars;
260 | }
261 |
262 | sublog(type: LOGTYPE, ...message: any) {
263 | switch (type) {
264 | case 'DISABLE':
265 | break;
266 | case 'VERBOSE':
267 | console.info(type, ...message);
268 | break;
269 | case 'DEBUG':
270 | console.debug(type, ...message);
271 | break;
272 | case 'WARN':
273 | console.warn(type, ...message);
274 | break;
275 | }
276 | }
277 |
278 | log(type: LOGTYPE, ...message: any) {
279 | switch (this._log) {
280 | case 'DISABLE':
281 | break;
282 | case 'VERBOSE':
283 | this.sublog(type, message);
284 | break;
285 | case 'DEBUG':
286 | if (type == 'DEBUG') {
287 | this.sublog(type, message);
288 | }
289 | break;
290 | case 'WARN':
291 | if (type == 'WARN') {
292 | this.sublog(type, message);
293 | }
294 | break;
295 | }
296 | }
297 |
298 | async startRendering() {
299 | window.requestAnimationFrame((timestamp) => {
300 | this.previous = timestamp;
301 | this.animationHandle = requestAnimationFrame(this.render.bind(this));
302 | });
303 | }
304 |
305 | render(timestamp: number) {
306 | if (this.stop === true) {
307 | if (this.animationHandle) {
308 | this.renderDiv.remove();
309 | cancelAnimationFrame(this.animationHandle);
310 | }
311 | } else {
312 | this.dt = (timestamp - this.previous) / 1000.0;
313 | this.previous = timestamp;
314 | this.display(this.video.currentTime);
315 | this.animationHandle = requestAnimationFrame(this.render.bind(this));
316 | }
317 | }
318 |
319 | destroy() {
320 | // console.debug('STOPPED::');
321 | this.stop = true;
322 | }
323 |
324 | display(time: number) {
325 | this.currentTime = time;
326 | this.clear();
327 | const slicesToDisplay = this.getSlices(time);
328 | slicesToDisplay.forEach((dialogue) => {
329 | this.showDialogue(dialogue, time);
330 | });
331 | }
332 |
333 | charsToString(chars: Char[]): string {
334 | return chars.reduce((acc, v) => {
335 | return (acc += v.kind == CHARKIND.NEWLINE ? '\n' : v.c);
336 | }, '');
337 | }
338 |
339 | getSlices(time: number): PreProceesedAss[] {
340 | return this.ppass.filter((dialogue) => {
341 | return dialogue.start <= time && dialogue.end >= time;
342 | });
343 | }
344 |
345 | getLineHeights(layer: Layer, lines: Char[][]): number[] {
346 | let heights: number[] = [];
347 |
348 | let currentMaxHeight = 0;
349 | lines.forEach((line) => {
350 | line.forEach((char) => {
351 | if (char.kind === CHARKIND.NORMAL) {
352 | let font = this.computeStyle(char.style, 1, layer);
353 | this.applyOverrideTag(char.tag, font);
354 | this.applyFont(font, layer);
355 | let calc =
356 | layer.ctx.measureText(char.c).fontBoundingBoxAscent +
357 | layer.ctx.measureText(char.c).fontBoundingBoxDescent;
358 | if (calc > currentMaxHeight) {
359 | currentMaxHeight = calc;
360 | }
361 | }
362 | });
363 | heights.push(currentMaxHeight);
364 | currentMaxHeight = 0;
365 | });
366 |
367 | return heights;
368 | }
369 |
370 | countLines(chars: Char[]): number {
371 | return chars.filter((c) => c.kind === CHARKIND.NEWLINE).length + 1;
372 | }
373 |
374 | lineWidth(layer: Layer, chars: Char[]) {
375 | let w = 0;
376 | chars.forEach((char) => {
377 | if (char.kind === CHARKIND.NORMAL) {
378 | let font = this.computeStyle(char.style, 1, layer);
379 | this.applyOverrideTag(char.tag, font);
380 | this.applyFont(font, layer);
381 | w += layer.ctx.measureText(char.c).width + font.t.fsp;
382 | }
383 | });
384 |
385 | return w;
386 | }
387 |
388 | lines(chars: Char[]): Char[][] {
389 | let lines: Char[][] = [];
390 | let buff: Char[] = [];
391 |
392 | chars.forEach((char) => {
393 | switch (char.kind) {
394 | case CHARKIND.NEWLINE:
395 | lines.push(buff);
396 | buff = [];
397 | break;
398 | case CHARKIND.NORMAL:
399 | buff.push(char);
400 | break;
401 | }
402 | });
403 |
404 | if (buff.length > 0) {
405 | lines.push(buff);
406 | }
407 |
408 | return lines;
409 | }
410 |
411 | showDialogue(d: PreProceesedAss, time: number) {
412 | const layer = this.getLayer(d.layer);
413 | if (layer) {
414 | let font = this.computeStyle(d.style, d.alignment, layer);
415 |
416 | const lines = this.lines(d.chars);
417 | const lineHeights = this.getLineHeights(layer, lines);
418 | const lineHeight = Math.max(...lineHeights);
419 | const linesCount = this.countLines(d.chars);
420 | const totalHeight = lineHeight * linesCount;
421 | let cX = 0;
422 | let cY = 0;
423 | let baseX = 0;
424 | let currentOpacity = 1;
425 |
426 | let customPosition = false;
427 | let rotationOrigin: Vector2 | undefined;
428 | const Xratio = layer.canvas.width / this.playerResX;
429 | const Yratio = layer.canvas.height / this.playerResY;
430 |
431 | if (d.pos) {
432 | customPosition = true;
433 | baseX = d.pos.x * Xratio;
434 | cX = baseX;
435 | cY = d.pos.y * Yratio;
436 | }
437 |
438 | if (d.move) {
439 | customPosition = true;
440 |
441 | let startPosition = new Vector2(d.move.from.x * Xratio, d.move.from.y * Yratio);
442 | let endPosition = new Vector2(d.move.to.x * Xratio, d.move.to.y * Yratio);
443 | let actualPosition = vectorLerp(
444 | startPosition,
445 | endPosition,
446 | (time - d.start) / (d.end - d.start)
447 | );
448 |
449 | baseX = actualPosition.x;
450 | cX = baseX;
451 | cY = actualPosition.y;
452 | }
453 |
454 | if (d.rotationOrigin)
455 | rotationOrigin = new Vector2(d.rotationOrigin.x * Xratio, d.rotationOrigin.y * Yratio);
456 |
457 | if (d.fade) {
458 | switch (d.fade.type) {
459 | case FadeKind.Simple:
460 | currentOpacity = getOpacity(d.fade, d.start * 1000, d.end * 1000, time * 1000);
461 | break;
462 | case FadeKind.Complex:
463 | currentOpacity = getOpacityComplex(d.fade, d.start * 1000, d.end * 1000, time * 1000);
464 | break;
465 | }
466 | }
467 |
468 | d.chars.forEach((char) => {
469 | switch (char.kind) {
470 | case CHARKIND.NEWLINE:
471 | cX = baseX;
472 | cY += lineHeight;
473 | break;
474 | case CHARKIND.NORMAL:
475 | font = this.computeStyle(char.style, d.alignment, layer);
476 | this.applyOverrideTag(char.tag, font);
477 | this.applyFont(font, layer);
478 | const w = layer.ctx.measureText(char.c).width + font.t.fsp;
479 | char.pos.x = cX;
480 | char.pos.y = cY;
481 | char.w = w;
482 | cX += w;
483 | break;
484 | }
485 | });
486 |
487 | const margin = this.upscaleMargin(d.margin);
488 |
489 | lines.forEach((line) => {
490 | // WARN: To debug
491 | const lineWidth = this.lineWidth(layer, line);
492 |
493 | if (!customPosition) {
494 | switch (font.textAlign) {
495 | case Align.Left:
496 | line.forEach((char) => {
497 | if (char.kind == CHARKIND.NORMAL) char.pos.x += margin.left;
498 | });
499 | break;
500 | case Align.Center:
501 | line.forEach((char) => {
502 | if (char.kind == CHARKIND.NORMAL)
503 | char.pos.x += (layer.canvas.width - lineWidth) / 2;
504 | });
505 | break;
506 | case Align.Right:
507 | line.forEach((char) => {
508 | if (char.kind == CHARKIND.NORMAL)
509 | char.pos.x += layer.canvas.width - lineWidth - margin.right;
510 | });
511 | break;
512 | default:
513 | line.forEach((char) => {
514 | if (char.kind == CHARKIND.NORMAL) char.pos.x += margin.left;
515 | });
516 | break;
517 | }
518 | switch (font.textBaseline) {
519 | case Baseline.Bottom:
520 | line.forEach((char) => {
521 | if (char.kind == CHARKIND.NORMAL)
522 | char.pos.y +=
523 | layer.canvas.height -
524 | (lines.length > 1 ? totalHeight / lines.length : 0) -
525 | margin.vertical;
526 | });
527 | break;
528 | case Baseline.Middle:
529 | line.forEach((char) => {
530 | if (char.kind == CHARKIND.NORMAL)
531 | char.pos.y +=
532 | (layer.canvas.height - totalHeight) / 2 +
533 | (lines.length > 1 ? totalHeight / lines.length : lineHeight);
534 | });
535 | break;
536 | case Baseline.Top:
537 | line.forEach((char) => {
538 | if (char.kind == CHARKIND.NORMAL) char.pos.y += margin.vertical + lineHeight / 2;
539 | });
540 | break;
541 | default:
542 | line.forEach((char) => {
543 | if (char.kind == CHARKIND.NORMAL)
544 | char.pos.y +=
545 | layer.canvas.height -
546 | (lines.length > 1 ? totalHeight / lines.length : 0) -
547 | margin.vertical;
548 | });
549 | break;
550 | }
551 | } else {
552 | switch (font.textAlign) {
553 | case Align.Left:
554 | break;
555 | case Align.Center:
556 | line.forEach((char) => {
557 | if (char.kind == CHARKIND.NORMAL) char.pos.x -= lineWidth / 2;
558 | });
559 | break;
560 | case Align.Right:
561 | // line.forEach((char) => {
562 | // if (char.kind == CHARKIND.NORMAL) char.pos.x += lineWidth;
563 | // });
564 | break;
565 | default:
566 | break;
567 | }
568 | }
569 | });
570 |
571 | let currentWord: Char[] = [];
572 | let currentFont: StyleDescriptor | null = null;
573 | let words: Word[] = [];
574 |
575 | let currentHash = 0;
576 |
577 | d.chars.forEach((char) => {
578 | if (char.kind == CHARKIND.NORMAL) {
579 | let font = this.computeStyle(char.style, d.alignment, layer);
580 | this.applyOverrideTag(char.tag, font);
581 |
582 | let fHash = this.getFontHash(font);
583 |
584 | if (currentHash !== fHash) {
585 | if (currentWord.length > 0) {
586 | if (currentFont !== null) {
587 | words.push({
588 | font: currentFont,
589 | value: currentWord,
590 | w: chunkCharWidth(currentWord)
591 | });
592 |
593 | currentWord = [char];
594 | currentFont = font;
595 | currentHash = fHash;
596 | }
597 | } else {
598 | currentFont = font;
599 | currentWord.push(char);
600 | currentHash = fHash;
601 | }
602 | } else {
603 | currentFont = font;
604 | currentWord.push(char);
605 | currentHash = fHash;
606 | }
607 | } else {
608 | if (currentFont !== null) {
609 | words.push({
610 | font: currentFont,
611 | value: currentWord,
612 | w: chunkCharWidth(currentWord)
613 | });
614 |
615 | currentWord = [];
616 | currentFont = null;
617 | }
618 | }
619 | });
620 |
621 | if (currentWord.length > 0) {
622 | if (currentFont !== null) {
623 | words.push({
624 | font: currentFont,
625 | value: currentWord,
626 | w: chunkCharWidth(currentWord)
627 | });
628 |
629 | currentWord = [];
630 | currentFont = null;
631 | }
632 | }
633 |
634 | words.forEach((word) => {
635 | word.font.opacity = currentOpacity;
636 | layer.ctx.save();
637 | this.drawWord(word, time, d.start, layer);
638 | layer.ctx.restore();
639 | });
640 | }
641 | }
642 |
643 | getFontHash(font: StyleDescriptor): number {
644 | return stringHash(JSON.stringify(font));
645 | }
646 |
647 | drawWord(word: Word, time: number, startTime: number, layer: Layer, debug = false) {
648 | let str = chunkCharToString(word.value);
649 | for (let i = 0; i < word.font.customAnimations.length; i++) {
650 | const ca = word.font.customAnimations[i] as CustomAnimation;
651 | if (startTime * 1000 + ca.t1 <= time * 1000 && time * 1000 <= startTime * 1000 + ca.t2) {
652 | const end = startTime * 1000 + ca.t2;
653 | const start = startTime * 1000 + ca.t1;
654 | const t = (time * 1000 - start) / (end - start);
655 |
656 | for (const field in ca.tag) {
657 | switch (field) {
658 | case 'a1':
659 | case 'a3':
660 | case 'a4':
661 | word.font.colors[field] = lerp(
662 | 255,
663 | Math.abs(parseAlpha(ca.tag[field] as string) - 255),
664 | t
665 | );
666 | break;
667 | case 'blur':
668 | case 'xshad':
669 | case 'yshad':
670 | case 'xbord':
671 | case 'ybord':
672 | word.font[field] = lerp(0, ca.tag[field] as number, t);
673 | break;
674 | case 'fax':
675 | case 'fay':
676 | case 'frx':
677 | case 'fry':
678 | case 'frz':
679 | case 'fscx':
680 | case 'fscy':
681 | word.font.t[field] = lerp(0, ca.tag[field] as number, t);
682 | break;
683 | case 'fs':
684 | word.font.fontsize = this.upscale(
685 | lerp(0, ca.tag[field] as number, t),
686 | this.playerResY,
687 | this.layers[0]?.canvas.height || 0
688 | );
689 | break;
690 | case 'fsp':
691 | word.font.t.fsp = this.upscale(
692 | lerp(0, ca.tag[field] as number, t),
693 | this.playerResX,
694 | this.layers[0]?.canvas.width || this.playerResX
695 | );
696 | break;
697 | default:
698 | break;
699 | }
700 | }
701 | }
702 | }
703 |
704 | this.applyFont(word.font, layer);
705 | const wordHead = word.value[0] as Char;
706 |
707 | if (wordHead.kind === CHARKIND.NORMAL) {
708 | if (word.font.borderStyle !== 3) {
709 | if (word.font.xbord !== 0 || word.font.ybord !== 0) {
710 | layer.ctx.strokeText(str, wordHead.pos.x, wordHead.pos.y);
711 | }
712 | }
713 |
714 | let metrics = layer.ctx.measureText(str);
715 |
716 | layer.ctx.fillText(str, wordHead.pos.x, wordHead.pos.y);
717 |
718 | if (word.font.underline) {
719 | const y = wordHead.pos.y + metrics.emHeightDescent;
720 | layer.ctx.fillRect(wordHead.pos.x, y, metrics.width, (layer.canvas.height * 0.2) / 100);
721 | }
722 | if (word.font.strikeout) {
723 | const y = wordHead.pos.y - metrics.hangingBaseline / 2;
724 | layer.ctx.shadowOffsetX = 0;
725 | layer.ctx.shadowOffsetY = 0;
726 | layer.ctx.fillRect(wordHead.pos.x, y, metrics.width, (layer.canvas.height * 0.2) / 100);
727 | }
728 |
729 | if (word.font.borderStyle === 3) {
730 | this.drawTextBackground(
731 | wordHead.pos,
732 | metrics.actualBoundingBoxAscent + metrics.fontBoundingBoxDescent,
733 | metrics.width,
734 | word.font
735 | );
736 | }
737 | }
738 | }
739 |
740 | drawTextBackground(pos: Vector2, height: number, width: number, font: StyleDescriptor) {
741 | const layer = this.layers[0] as Layer;
742 | layer.ctx.save();
743 | layer.ctx.beginPath();
744 | layer.ctx.fillStyle = font.colors.c2;
745 | layer.ctx.fillRect(pos.x, pos.y - height, width, height);
746 | layer.ctx.closePath();
747 | layer.ctx.restore();
748 | }
749 |
750 | upscaleY(y: number, baseCanvasHeight: number) {
751 | const canvasHeight = this.layers[0]?.canvas.height || this.playerResY;
752 | return (canvasHeight * y) / baseCanvasHeight;
753 | }
754 | upscaleX(x: number, baseCanvasWidth: number) {
755 | const canvasWidth = this.layers[0]?.canvas.width || this.playerResX;
756 | return (canvasWidth * x) / baseCanvasWidth;
757 | }
758 |
759 | clearLayer(layer: number) {
760 | this.layers[layer]?.ctx.clearRect(
761 | 0,
762 | 0,
763 | this.layers[layer]?.canvas.width as number,
764 | this.layers[layer]?.canvas.height as number
765 | );
766 | }
767 |
768 | clear() {
769 | this.layers.forEach((layer) => {
770 | layer.ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height);
771 | });
772 | }
773 |
774 | upscalePosition(pos: Position) {
775 | return {
776 | x: this.upscale(pos.x, this.playerResX, this.layers[0]?.canvas.width || this.playerResX),
777 | y: this.upscale(pos.y, this.playerResY, this.layers[0]?.canvas.height || this.playerResY)
778 | };
779 | }
780 |
781 | upscaleMargin(margin: Margin) {
782 | return {
783 | left: this.upscale(
784 | margin.left,
785 | this.playerResX,
786 | this.layers[0]?.canvas.width || this.playerResX
787 | ),
788 | right: this.upscale(
789 | margin.right,
790 | this.playerResX,
791 | this.layers[0]?.canvas.width || this.playerResX
792 | ),
793 | vertical: this.upscale(
794 | margin.vertical,
795 | this.playerResY,
796 | this.layers[0]?.canvas.height || this.playerResY
797 | )
798 | };
799 | }
800 |
801 | applyOverrideTag(tag: CompiledTag, font: StyleDescriptor) {
802 | if (tag.b !== undefined) font.bold = tag.b === 1;
803 | if (tag.i !== undefined) font.italic = tag.i === 1;
804 | if (tag.u !== undefined) font.underline = tag.u === 1;
805 | if (tag.s !== undefined) font.strikeout = tag.s === 1;
806 | if (tag.fn !== undefined) font.fontname = tag.fn;
807 | if (tag.q !== undefined) font.t.q = tag.q;
808 | if (tag.fs !== undefined)
809 | font.fontsize = this.upscale(tag.fs, this.playerResY, this.layers[0]?.canvas.height || 0);
810 | if (tag.fscx !== undefined) font.t.fscx = tag.fscx;
811 | if (tag.fscy !== undefined) font.t.fscy = tag.fscy;
812 | if (tag.frz !== undefined) font.t.frz = tag.frz;
813 | if (tag.frx !== undefined) font.t.frx = tag.frx;
814 | if (tag.fry !== undefined) font.t.fry = tag.fry;
815 | if (tag.fax !== undefined) font.t.fax = tag.fax;
816 | if (tag.fay !== undefined) font.t.fay = tag.fay;
817 | if (tag.fsp !== undefined) {
818 | font.t.fsp = this.upscale(
819 | tag.fsp,
820 | this.playerResX,
821 | this.layers[0]?.canvas.width || this.playerResX
822 | );
823 | }
824 |
825 | if (tag.t !== undefined) font.customAnimations = tag.t;
826 |
827 | if (tag.c1 !== undefined) font.colors.c1 = swapBBGGRR(tag.c1);
828 | if (tag.c3 !== undefined) font.colors.c3 = swapBBGGRR(tag.c3);
829 | if (tag.c4 !== undefined) font.colors.c4 = swapBBGGRR(tag.c4);
830 | if (tag.a1 !== undefined) font.colors.a1 = parseAlpha(tag.a1);
831 | if (tag.a3 !== undefined) font.colors.a3 = parseAlpha(tag.a3);
832 | if (tag.a4 !== undefined) font.colors.a4 = parseAlpha(tag.a4);
833 | if (tag.xshad !== undefined) font.xshad = tag.xshad;
834 | if (tag.yshad !== undefined) font.yshad = tag.yshad;
835 | if (tag.xbord !== undefined) font.xbord = tag.xbord;
836 | if (tag.ybord !== undefined) font.ybord = tag.ybord;
837 | if (tag.blur !== undefined) font.blur = tag.blur;
838 | }
839 |
840 | upscale(x: number, firstcomp: number, secondcomp: number) {
841 | return (ruleOfThree(firstcomp, secondcomp) * x) / 100;
842 | }
843 |
844 | fontDecriptorString(font: StyleDescriptor) {
845 | return `${font.bold ? 'bold ' : ''}${font.italic ? 'italic ' : ''}${font.fontsize.toFixed(
846 | 3
847 | )}px "${font.fontname}"`;
848 | }
849 |
850 | computeStyle(name: string, alignment: number, layer: Layer): StyleDescriptor {
851 | const style = this.styles[name] as CompiledASSStyle;
852 | if (style === undefined) {
853 | // TODO: fallbackFont when there is no style
854 | // Fallbacks most of the time to Arial
855 | this.log('WARN', `[ass-html5:renderer] no corresponding style "${name}" found`);
856 | }
857 | const {
858 | fn, // font name
859 | fs, // font size
860 | a1, // primary alpha
861 | a2, // secondary alpha
862 | a3, // outline alpha
863 | c4, // shadow color
864 | a4, // shadow alpha
865 | b, // bold
866 | i, // italic
867 | u, // underline
868 | s, // strikeout
869 | fscx, // font scale x
870 | fscy, // font scale y
871 | fsp, // font spacing
872 | frz, // font rotation z
873 | xbord, // x border
874 | ybord, // y border
875 | xshad, // x shadow
876 | yshad, // y shadow
877 | fe, // font encoding
878 | q // wrap style
879 | } = style.tag;
880 |
881 | const { PrimaryColour, OutlineColour, SecondaryColour, BorderStyle } = style.style;
882 |
883 | const font: StyleDescriptor = {
884 | fontsize: this.upscale(fs, this.playerResY, this.layers[0]?.canvas.height || this.playerResY),
885 | fontname: fn,
886 | bold: b === 1,
887 | italic: i === 1,
888 | underline: u === 1,
889 | strikeout: s === 1,
890 | colors: {
891 | c1: convertAegisubColorToHex(PrimaryColour),
892 | c2: convertAegisubColorToHex(SecondaryColour),
893 | c3: convertAegisubColorToHex(OutlineColour),
894 | c4,
895 | a1: parseAlpha(a1),
896 | a2: parseAlpha(a2),
897 | a3: parseAlpha(a3),
898 | a4: parseAlpha(a4)
899 | },
900 | t: {
901 | fscx: fscx,
902 | fscy: fscy,
903 | frz: frz,
904 | frx: 0,
905 | fry: 0,
906 | fsp: this.upscale(fsp, this.playerResX, layer.canvas.width),
907 | q: q
908 | },
909 | customAnimations: [],
910 | xbord: xbord,
911 | ybord: ybord,
912 | xshad: xshad,
913 | yshad: yshad,
914 | blur: 0,
915 | fe: fe,
916 | borderStyle: BorderStyle,
917 | opacity: 1,
918 | textAlign: this.getAlignment(alignment),
919 | textBaseline: this.getBaseLine(alignment)
920 | };
921 |
922 | this.applyFont(font, layer);
923 |
924 | return font;
925 | }
926 |
927 | applyFont(font: StyleDescriptor, layer: Layer) {
928 | layer.ctx.font = this.fontDecriptorString(font);
929 | layer.ctx.fillStyle = blendAlpha(font.colors.c1, font.colors.a1);
930 | layer.ctx.strokeStyle = blendAlpha(font.colors.c3, font.colors.a3);
931 | layer.ctx.letterSpacing = `${font.t.fsp}px`;
932 | layer.ctx.shadowOffsetX = this.upscale(
933 | font.xshad,
934 | this.playerResX,
935 | this.layers[0]?.canvas.width || this.playerResX
936 | );
937 | layer.ctx.shadowOffsetY = this.upscale(
938 | font.yshad,
939 | this.playerResY,
940 | this.layers[0]?.canvas.height || this.playerResY
941 | );
942 | layer.ctx.shadowBlur = this.upscale(
943 | font.blur,
944 | this.playerResY,
945 | this.layers[0]?.canvas.height || this.playerResY
946 | );
947 | layer.ctx.shadowColor = blendAlpha(font.colors.c4, font.colors.a4);
948 | layer.ctx.lineWidth =
949 | this.upscale(font.xbord, this.playerResX, this.layers[0]?.canvas.width || this.playerResX) +
950 | this.upscale(font.ybord, this.playerResY, this.layers[0]?.canvas.height || this.playerResY);
951 | layer.ctx.lineCap = 'round';
952 | layer.ctx.lineJoin = 'round';
953 | layer.ctx.globalAlpha = font.opacity;
954 | }
955 |
956 | getAlignment(alignment: number) {
957 | // 1 = (bottom) left
958 | // 2 = (bottom) center
959 | // 3 = (bottom) right
960 | // 4 = (middle) left
961 | // 5 = (middle) center
962 | // 6 = (middle) right
963 | // 7 = (top) left
964 | // 8 = (top) center
965 | // 9 = (top) right
966 | switch (alignment) {
967 | case 1:
968 | case 4:
969 | case 7:
970 | return Align.Left;
971 | case 2:
972 | case 5:
973 | case 8:
974 | return Align.Center;
975 | case 3:
976 | case 6:
977 | case 9:
978 | return Align.Right;
979 | default:
980 | return Align.Start;
981 | }
982 | }
983 |
984 | getBaseLine(alignment: number) {
985 | // 1 = (bottom) left
986 | // 2 = (bottom) center
987 | // 3 = (bottom) right
988 | // 4 = (middle) left
989 | // 5 = (middle) center
990 | // 6 = (middle) right
991 | // 7 = (top) left
992 | // 8 = (top) center
993 | // 9 = (top) right
994 | switch (alignment) {
995 | case 1:
996 | case 2:
997 | case 3:
998 | return Baseline.Bottom;
999 | case 4:
1000 | case 5:
1001 | case 6:
1002 | return Baseline.Middle;
1003 | case 7:
1004 | case 8:
1005 | case 9:
1006 | return Baseline.Top;
1007 | default:
1008 | return Baseline.Alphabetic;
1009 | }
1010 | }
1011 | }
1012 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { CompiledASSStyle, Dialogue } from 'ass-compiler';
2 | import type { CompiledTag, ParsedTag } from 'ass-compiler/types/tags';
3 | import { Vector2 } from './utils';
4 |
5 | export type OnInitSizes = {
6 | width: number;
7 | height: number;
8 | x: number;
9 | y: number;
10 | };
11 |
12 | export enum Baseline {
13 | Bottom,
14 | Middle,
15 | Top,
16 | Alphabetic
17 | }
18 |
19 | export enum Align {
20 | Left,
21 | Center,
22 | Right,
23 | Start
24 | }
25 |
26 | export type CustomAnimation = {
27 | t1: number;
28 | t2: number;
29 | accel: number;
30 | tag: CompiledTag;
31 | };
32 |
33 | export type StyleDescriptor = {
34 | fontname: string;
35 | fontsize: number;
36 | bold: boolean;
37 | italic: boolean;
38 | underline: boolean;
39 | strikeout: boolean;
40 | colors: Colors;
41 | /** font transformation */
42 | t: FontTransfomation;
43 | customAnimations: CustomAnimation[];
44 | /** x border */
45 | xbord: number;
46 | /** y border */
47 | ybord: number;
48 | xshad: number;
49 | yshad: number;
50 | /** shadow blur */
51 | blur: number;
52 | /** font encoding */
53 | fe?: number;
54 | borderStyle: number;
55 | opacity: number;
56 | textAlign: Align;
57 | textBaseline: Baseline;
58 | };
59 |
60 | export type Layer = {
61 | canvas: HTMLCanvasElement;
62 | ctx: CanvasRenderingContext2D;
63 | };
64 |
65 | export type Colors = {
66 | c1: string;
67 | a1: number;
68 | c2: string;
69 | a2: number;
70 | c3: string;
71 | a3: number;
72 | c4: string;
73 | a4: number;
74 | };
75 |
76 | export type FontTransfomation = {
77 | /** font scale x */
78 | fscx: number;
79 | /** font scale y */
80 | fscy: number;
81 | /** font rotation z*/
82 | frz: number;
83 | /** font rotation x*/
84 | frx: number;
85 | /** font rotation y*/
86 | fry: number;
87 | /** font shear x */
88 | fax?: number;
89 | /** font shear y */
90 | fay?: number;
91 | /** font spacing */
92 | fsp: number;
93 | /** wrap style */
94 | q: 0 | 2 | 1 | 3;
95 | };
96 |
97 | export type Tag = { [K in keyof ParsedTag]: ParsedTag[K] };
98 |
99 | export type Override = {
100 | dialogue: Dialogue;
101 | style: CompiledASSStyle;
102 | };
103 |
104 | export type Styles = { [styleName: string]: CompiledASSStyle };
105 |
106 | export type Position = {
107 | x: number;
108 | y: number;
109 | };
110 |
111 | export type LOGTYPE = 'DISABLE' | 'VERBOSE' | 'DEBUG' | 'WARN';
112 |
113 | export enum CHARKIND {
114 | NEWLINE,
115 | NORMAL
116 | }
117 |
118 | export type Margin = { left: number; right: number; vertical: number };
119 | export type Char =
120 | | {
121 | kind: CHARKIND.NORMAL;
122 | pos: Vector2;
123 | c: string;
124 | w: number;
125 | tag: CompiledTag;
126 | style: string;
127 | ord: number;
128 | }
129 | | {
130 | kind: CHARKIND.NEWLINE;
131 | };
132 |
133 | export type Word = {
134 | w: number;
135 | font: StyleDescriptor;
136 | value: Char[];
137 | };
138 |
139 | export enum FadeKind {
140 | Simple,
141 | Complex
142 | }
143 | export type FadeAnimation =
144 | | {
145 | type: FadeKind.Simple;
146 | fadein: number;
147 | fadeout: number;
148 | }
149 | | {
150 | type: FadeKind.Complex;
151 | a1: number;
152 | a2: number;
153 | a3: number;
154 | t1: number;
155 | t2: number;
156 | t3: number;
157 | t4: number;
158 | };
159 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import { type Tag, type Char, CHARKIND, FadeAnimation, FadeKind } from './types';
2 | /**
3 | * Convert a color in RGBA format to Aegisub format
4 | * @param aegisubColor The color in Aegisub format
5 | * @returns The color in RGBA format
6 | */
7 | export function convertAegisubColorToHex(aegisubColor: string) {
8 | const colorValue = aegisubColor.replace(/&H|&/g, '');
9 |
10 | // Extract the individual color components from the Aegisub color value
11 | const blue = parseInt(colorValue.slice(2, 4), 16);
12 | const green = parseInt(colorValue.slice(4, 6), 16);
13 | const red = parseInt(colorValue.slice(6, 8), 16);
14 |
15 | // Create the RGBA
16 | const rgba = `rgb(${red}, ${green}, ${blue}, 1)`;
17 | const hex = rgbaToHex(rgba);
18 | return hex;
19 | }
20 |
21 | export function swapBBGGRR(color: string) {
22 | // color : #FF0008 -> #0800FF
23 | const colorValue = color.replace('#', '');
24 | const blue = colorValue.slice(0, 2);
25 | const green = colorValue.slice(2, 4);
26 | const red = colorValue.slice(4, 6);
27 | return `#${red}${green}${blue}`;
28 | }
29 |
30 | export function changeAlpha(color: string, alpha: number) {
31 | if (color.startsWith('rgba')) {
32 | return color.replace(/rgba\((\d+), (\d+), (\d+), (\d+)\)/, `rgba($1, $2, $3, ${alpha})`);
33 | } else {
34 | // hexToRgba
35 | const rgba = hexToRgba(color);
36 | return rgba.replace(/rgba\((\d+), (\d+), (\d+), (\d+)\)/, `rgba($1, $2, $3, ${alpha})`);
37 | }
38 | }
39 |
40 | export function getAlphaFromColor(color: string) {
41 | if (color.startsWith('rgba')) {
42 | const alpha = color.replace(/rgba\((\d+), (\d+), (\d+), (\d+)\)/, '$4');
43 | // console.debug(color, "getAlphaFromColor", "rgba")
44 | return parseFloat(alpha);
45 | } else {
46 | // hexToRgba
47 | const rgba = hexToRgba(color);
48 | // console.debug(rgba, "getAlphaFromColor", "hex")
49 | return parseFloat(rgba.replace(/rgba\((\d+), (\d+), (\d+), (\d+)\)/, '$4'));
50 | }
51 | }
52 |
53 | export function rgbaToHex(rgba: string) {
54 | const components = rgba.match(/\d+/g) as string[]; // Extract numeric values from RGBA string
55 | let red = parseInt(components[0] as string);
56 | let green = parseInt(components[1] as string);
57 | let blue = parseInt(components[2] as string);
58 | let alpha = parseFloat(components[3] as string);
59 |
60 | let redHex = red.toString(16).padStart(2, '0');
61 | let greenHex = green.toString(16).padStart(2, '0');
62 | let blueHex = blue.toString(16).padStart(2, '0');
63 |
64 | let rgbHex = '#' + redHex + greenHex + blueHex;
65 |
66 | if (alpha !== 1) {
67 | let alphaHex = Math.round(alpha * 255)
68 | .toString(16)
69 | .padStart(2, '0');
70 | return rgbHex + alphaHex;
71 | }
72 |
73 | return rgbHex;
74 | }
75 |
76 | export function hexToRgba(hex: string, defaultAlpha = 1) {
77 | const hexValue = hex.replace('#', ''); // Remove '#' if present
78 | const isShortHex = hexValue.length === 3 || hexValue.length === 4;
79 |
80 | let redHex, greenHex, blueHex, alphaHex;
81 | if (isShortHex) {
82 | redHex = (hexValue[0] as string) + (hexValue[0] as string);
83 | greenHex = (hexValue[1] as string) + (hexValue[1] as string);
84 | blueHex = (hexValue[2] as string) + (hexValue[2] as string);
85 | if (hexValue.length === 4) {
86 | alphaHex = (hexValue[3] as string) + (hexValue[3] as string);
87 | } else {
88 | alphaHex = 'FF'; // Default alpha value if not provided
89 | }
90 | } else {
91 | redHex = hexValue.substring(0, 2);
92 | greenHex = hexValue.substring(2, 4);
93 | blueHex = hexValue.substring(4, 6);
94 | if (hexValue.length === 8) {
95 | alphaHex = hexValue.substring(6, 8);
96 | } else {
97 | alphaHex = 'FF'; // Default alpha value if not provided
98 | }
99 | }
100 |
101 | const red = parseInt(redHex, 16);
102 | const green = parseInt(greenHex, 16);
103 | const blue = parseInt(blueHex, 16);
104 | const alpha = parseInt(alphaHex, 16) / 255;
105 |
106 | return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + alpha + ')';
107 | }
108 |
109 | export function insertTags(tags: Tag[], tag: Tag) {
110 | tags.forEach((singleTag) => {
111 | // if the tag is already present, it will be overwritten
112 | tag = { ...tag, ...singleTag };
113 | });
114 | return tag;
115 | }
116 |
117 | export function ruleOfThree(value: number, valueMin: number) {
118 | return (valueMin * 100) / value;
119 | }
120 |
121 | export function genRandomString(ln: number) {
122 | const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
123 | let randomString = '';
124 |
125 | for (let i = 0; i < ln; i++) {
126 | const randomIndex = Math.floor(Math.random() * characters.length);
127 | randomString += characters.charAt(randomIndex);
128 | }
129 |
130 | return randomString;
131 | }
132 |
133 | export function randomId(parts: number, separator = '-', prefix = '', ln = 10) {
134 | let partsArray: string[] = [];
135 | for (let i = 0; i < parts; i++) {
136 | partsArray.push(genRandomString(ln));
137 | }
138 | return prefix + partsArray.join(separator);
139 | }
140 |
141 | export function stringHash(str: string) {
142 | let hash = 0;
143 |
144 | if (str.length == 0) return hash;
145 |
146 | for (let i = 0; i < str.length; i++) {
147 | let char = str.charCodeAt(i);
148 | hash = (hash << 5) - hash + char;
149 | hash = hash & hash;
150 | }
151 |
152 | return hash;
153 | }
154 |
155 | export function chunkCharWidth(chars: Char[]) {
156 | let w = 0;
157 | for (let i = 0; i < chars.length; i++) {
158 | let char = chars[i] as Char;
159 | if (char.kind == CHARKIND.NORMAL) {
160 | w += char.w;
161 | }
162 | }
163 |
164 | return w;
165 | }
166 |
167 | export function chunkCharToString(chars: Char[]) {
168 | let w = '';
169 | for (let i = 0; i < chars.length; i++) {
170 | let char = chars[i] as Char;
171 | if (char.kind == CHARKIND.NORMAL) {
172 | w += char.c;
173 | }
174 | }
175 |
176 | return w;
177 | }
178 |
179 | export function newRender(
180 | top: number,
181 | left: number,
182 | width: number,
183 | height: number,
184 | zIndex?: number,
185 | insertAfter?: HTMLElement
186 | ) {
187 | const render = document.createElement('div');
188 | render.id = randomId(2, '-', 'ASSRendererRender-', 5);
189 | render.style.position = 'absolute';
190 | render.style.width = width + 'px';
191 | render.style.height = height + 'px';
192 | render.style.top = top + 'px';
193 | render.style.left = left + 'px';
194 | render.style.pointerEvents = 'none';
195 | render.style.overflow = 'hidden';
196 | render.style.boxSizing = 'border-box';
197 | render.style.padding = '0px';
198 | render.style.margin = '0px';
199 | if (zIndex) {
200 | render.style.zIndex = zIndex.toString();
201 | }
202 |
203 | if (insertAfter) {
204 | insertAfter.after(render);
205 | } else {
206 | document.body.appendChild(render);
207 | }
208 |
209 | return render;
210 | }
211 |
212 | export function newCanvas(
213 | width: number,
214 | height: number,
215 | dataLayer = 0,
216 | layerName?: string,
217 | appendIn?: HTMLElement,
218 | insertAfter?: HTMLElement
219 | ) {
220 | const canvas = document.createElement('canvas');
221 | canvas.id = randomId(2, '-', 'Canvas-', 5);
222 | canvas.style.position = 'absolute';
223 | canvas.style.top = '0px';
224 | canvas.style.left = '0px';
225 | canvas.style.pointerEvents = 'none';
226 | canvas.width = width;
227 | canvas.height = height;
228 | canvas.dataset.layer = dataLayer.toString();
229 | canvas.dataset.identifier = uuidgen();
230 |
231 | if (layerName) {
232 | canvas.dataset.name = layerName;
233 | }
234 |
235 | if (insertAfter) {
236 | insertAfter.after(canvas);
237 | } else {
238 | if (!appendIn) {
239 | appendIn = document.body;
240 | }
241 | appendIn.appendChild(canvas);
242 | }
243 | return canvas;
244 | }
245 |
246 | export function uuidgen() {
247 | const v4 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
248 | return v4.replace(/[xy]/g, (c) => {
249 | const r = (Math.random() * 16) | 0;
250 | const v = c === 'x' ? r : (r & 0x3) | 0x8;
251 | return v.toString(16);
252 | });
253 | }
254 |
255 | export function parseAlpha(of: string) {
256 | const a = `0x${of}`;
257 | return parseInt(a, 16);
258 | }
259 |
260 | export function blendAlpha(color: string, alpha: number) {
261 | color = color.replace('#', '');
262 | // color = FFFFFF
263 | // alpha = 0x80
264 | // return rgba(255, 255, 255, 0.5)
265 | const red = parseInt(color.substring(0, 2), 16);
266 | const green = parseInt(color.substring(2, 4), 16);
267 | const blue = parseInt(color.substring(4, 6), 16);
268 | return `rgba(${red}, ${green}, ${blue}, ${alpha == 0 ? 1 : alpha / 255})`;
269 | }
270 |
271 | export class Vector2 {
272 | x: number;
273 | y: number;
274 | constructor(x: number = 0, y: number = 0) {
275 | this.x = x;
276 | this.y = y;
277 | }
278 |
279 | add(rhs: Vector2): Vector2 {
280 | return new Vector2(this.x + rhs.x, this.y + rhs.y);
281 | }
282 | sub(rhs: Vector2): Vector2 {
283 | return new Vector2(this.x - rhs.x, this.y - rhs.y);
284 | }
285 | mul(i: number): Vector2 {
286 | return new Vector2(this.x * i, this.y * i);
287 | }
288 | }
289 |
290 | /**
291 | * Interpolate a vector2 between tow vector2
292 | * @param start - starting point
293 | * @param end - the end point
294 | * @param t a value between 0 and 1
295 | * @returns A new Vector2 representing the interpolated point
296 | */
297 | export function vectorLerp(start: Vector2, end: Vector2, t: number): Vector2 {
298 | // start + (end - start) * t
299 | return start.add(end.sub(start).mul(t));
300 | }
301 |
302 | export function lerp(start: number, end: number, t: number): number {
303 | return start + (end - start) * t;
304 | }
305 |
306 | /**
307 | * Produce a fade-in and fade-out effect. The fadein and fadeout times are
308 | * given in milliseconds, ie. 1000 means one second. You can specify fadein or
309 | * fadeout as 0 (zero) to not have any fade effect on that end.
310 | */
311 | export function getOpacity(
312 | fade: Extract,
313 | startTime: number,
314 | endTime: number,
315 | time: number
316 | ): number {
317 | const fadeIn = startTime + fade.fadein;
318 | const fadeOut = endTime - fade.fadeout;
319 | if (time < fadeIn) {
320 | let t = (time - startTime) / (fadeIn - startTime);
321 | return lerp(0, 1, t);
322 | } else if (time >= fadeIn && time < fadeOut) {
323 | return 1;
324 | } else if (time >= fadeOut && time <= endTime) {
325 | let t = (time - fadeOut) / (endTime - fadeOut);
326 | return lerp(1, 0, t);
327 | } else {
328 | return -1;
329 | }
330 | }
331 |
332 | /**
333 | * Perform a five-part fade using three alpha values a1, a2 and a3 and four
334 | * times t1, t2, t3 and t4.
335 | *
336 | * The alpha values are given in decimal and are between 0 and 255, with 0
337 | * being fully visible and 255 being invisible. The time values are given in
338 | * milliseconds after the start of the line. All seven parameters are
339 | * required. (For most common fade effects the `\fad` tag works fine.)
340 | *
341 | * - Before t1, the line has alpha a1.
342 | * - Between t1 and t2 the line fades from alpha a1 to alpha a2.
343 | * - Between t2 and t3 the line has alpha a2 constantly.
344 | * - Between t3 and t4 the line fades from alpha a2 to alpha a3.
345 | * - After t4 the line has alpha a3.
346 | */
347 | export function getOpacityComplex(
348 | fade: Extract,
349 | startTime: number,
350 | endTime: number,
351 | time: number
352 | ): number {
353 | console.debug(fade);
354 |
355 | const t1 = startTime + fade.t1;
356 | const t2 = startTime + fade.t2;
357 | const t3 = startTime + fade.t3;
358 | const t4 = startTime + fade.t4;
359 |
360 | if (time < t1) {
361 | return fade.a1;
362 | } else if (time >= t1 && time < t2) {
363 | let t = (time - t1) / (t2 - t1);
364 | return lerp(fade.a1, fade.a2, t);
365 | } else if (time >= t2 && time < t3) {
366 | return fade.a2;
367 | } else if (time >= t3 && time < t4) {
368 | let t = (time - t3) / (t4 - t3);
369 | return lerp(fade.a2, fade.a3, t);
370 | } else if (time >= t4 && time <= endTime) {
371 | return fade.a3;
372 | } else {
373 | return -1;
374 | }
375 | }
376 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
4 | "module": "esnext" /* Specify what module code is generated. */,
5 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
6 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
7 | "strict": true /* Enable all strict type-checking options. */,
8 | "skipLibCheck": true /* Skip type checking all .d.ts files. */,
9 | "noUncheckedIndexedAccess": true,
10 | "noEmit": true,
11 | "removeComments": true,
12 | "lib": ["esnext", "dom"],
13 | "moduleResolution": "node"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'tsup';
2 |
3 | export default defineConfig({
4 | entry: ['src/ass.ts'],
5 | clean: false,
6 | dts: true,
7 | platform: 'browser',
8 | target: 'esnext',
9 | noExternal: ['ass-compiler'],
10 | name: 'ASS',
11 | globalName: 'ass',
12 | format: ['esm', 'cjs'],
13 | async onSuccess() {
14 | console.log(' END ' + Date().split(' ')[4]);
15 | }
16 | });
17 |
--------------------------------------------------------------------------------