@fcannizzaro/streamdeck-react 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,238 @@
1
+ export type ManifestController = "Encoder" | "Keypad";
2
+ export interface ManifestOSInfo {
3
+ platform: "mac" | "windows";
4
+ minimumVersion: string;
5
+ }
6
+ export interface ManifestNodejsInfo {
7
+ /**
8
+ * Node.js version to use.
9
+ * @default "24"
10
+ */
11
+ version: "20" | "24";
12
+ /**
13
+ * Debug configuration. `"enabled"` and `"break"` are shortcuts for
14
+ * `--inspect` and `--inspect-brk` respectively. A custom string is
15
+ * passed as-is (e.g. `"--inspect=127.0.0.1:8090"`).
16
+ */
17
+ debug?: string;
18
+ /** Enable profiler output. */
19
+ generateProfilerOutput?: boolean;
20
+ }
21
+ export interface ManifestStateInfo {
22
+ /** Path to state image (extension omitted). 72×72 and 144×144 @2x. */
23
+ image: string;
24
+ /** State name (shown in multi-action state selector). */
25
+ name?: string;
26
+ /** Default title text. */
27
+ title?: string;
28
+ /** Whether to show the title. */
29
+ showTitle?: boolean;
30
+ /** Title alignment. */
31
+ titleAlignment?: "bottom" | "middle" | "top";
32
+ /** Title color (hex). */
33
+ titleColor?: string;
34
+ /** Font family for the title. */
35
+ fontFamily?: string;
36
+ /** Font size for the title. */
37
+ fontSize?: number;
38
+ /** Font style for the title. */
39
+ fontStyle?: "" | "Bold" | "Bold Italic" | "Italic" | "Regular";
40
+ /** Whether the title is underlined. */
41
+ fontUnderline?: boolean;
42
+ /** Image shown when the action is in a multi-action. */
43
+ multiActionImage?: string;
44
+ }
45
+ export interface ManifestTriggerDescription {
46
+ /** Dial rotation description. */
47
+ rotate?: string;
48
+ /** Dial press description. */
49
+ push?: string;
50
+ /** Touch tap description. */
51
+ touch?: string;
52
+ /** Long touch description. */
53
+ longTouch?: string;
54
+ }
55
+ export interface ManifestEncoderInfo {
56
+ /**
57
+ * Touch screen layout. Pre-defined: `$X1`, `$A0`, `$A1`, `$B1`,
58
+ * `$B2`, `$C1`. Or a path to a custom `.json` layout file.
59
+ */
60
+ layout?: string;
61
+ /** Encoder icon (extension omitted). 72×72 and 144×144 @2x. */
62
+ icon?: string;
63
+ /** Background color for dial stack (hex). */
64
+ stackColor?: string;
65
+ /** Touchscreen background image (extension omitted). 200×100 and 400×200 @2x. */
66
+ background?: string;
67
+ /** Descriptions shown to the user for each interaction type. */
68
+ triggerDescription?: ManifestTriggerDescription;
69
+ }
70
+ export interface ManifestProfileInfo {
71
+ /** Path to .streamDeckProfile file (extension omitted). */
72
+ name: string;
73
+ /**
74
+ * Target device type.
75
+ *
76
+ * Common values:
77
+ * 0 = Stream Deck, 1 = Mini, 2 = XL, 5 = Pedal,
78
+ * 7 = Stream Deck +, 9 = Neo, 10 = Studio
79
+ */
80
+ deviceType: number;
81
+ /** Auto-install when plugin is installed. @default true */
82
+ autoInstall?: boolean;
83
+ /** Don't auto-switch to profile on first install. @default false */
84
+ dontAutoSwitchWhenInstalled?: boolean;
85
+ /** Profile is read-only. @default false */
86
+ readonly?: boolean;
87
+ }
88
+ export interface ActionManifestInfo {
89
+ /** Action display name in Stream Deck's action list. */
90
+ name: string;
91
+ /** Path to action icon (extension omitted). 20×20 and 40×40 @2x. */
92
+ icon: string;
93
+ /**
94
+ * Skip this action during auto-extraction for manifest generation.
95
+ * The action is still registered at runtime but excluded from the
96
+ * generated manifest.json.
97
+ *
98
+ * @default false
99
+ */
100
+ disabled?: boolean;
101
+ /** Hover tooltip in the actions list. */
102
+ tooltip?: string;
103
+ /**
104
+ * Custom states. When omitted, a single state is generated
105
+ * using the `icon` field as the state image.
106
+ * @default [{ image: icon }]
107
+ */
108
+ states?: ManifestStateInfo[];
109
+ /** Encoder config (layout, triggerDescription, background). */
110
+ encoder?: ManifestEncoderInfo;
111
+ /** Disable automatic state toggling. @default false */
112
+ disableAutomaticStates?: boolean;
113
+ /** Disable Stream Deck image caching. @default false */
114
+ disableCaching?: boolean;
115
+ /** Available in multi-actions. @default true */
116
+ supportedInMultiActions?: boolean;
117
+ /** Available in key logic actions (SD 7.0+). @default true */
118
+ supportedInKeyLogicActions?: boolean;
119
+ /** Visible in the actions list. @default true */
120
+ visibleInActionsList?: boolean;
121
+ /** Allow user to edit title. @default true */
122
+ userTitleEnabled?: boolean;
123
+ /** Action-specific property inspector HTML path. */
124
+ propertyInspectorPath?: string;
125
+ /** Action support URL. */
126
+ supportUrl?: string;
127
+ /** OS restriction for this action. */
128
+ os?: ("mac" | "windows")[];
129
+ /**
130
+ * Controller types.
131
+ *
132
+ * Auto-derived in bundler plugin:
133
+ * - `encoder` field present → `["Encoder"]`
134
+ * - otherwise → `["Keypad"]`
135
+ *
136
+ * @default ["Keypad"]
137
+ */
138
+ controllers?: [ManifestController, ManifestController?];
139
+ }
140
+ export interface ManifestActionSource {
141
+ uuid: string;
142
+ /** Presence indicates Keypad controller support. */
143
+ key?: unknown;
144
+ /** Presence indicates Encoder controller support. */
145
+ dial?: unknown;
146
+ /** Presence indicates Encoder controller support (touchstrip variant). */
147
+ touchStrip?: unknown;
148
+ /** Action manifest metadata. Required for manifest generation. */
149
+ info?: ActionManifestInfo;
150
+ }
151
+ export interface ManifestConfig extends PluginManifestInfo {
152
+ /**
153
+ * Action definitions from defineAction().
154
+ * Each action must have `info` populated with at least `name` and `icon`.
155
+ * Controllers are auto-derived from key/dial/touchStrip presence.
156
+ */
157
+ actions: ManifestActionSource[];
158
+ }
159
+ export interface PluginManifestInfo {
160
+ /**
161
+ * Unique plugin identifier in reverse-DNS format.
162
+ *
163
+ * All action UUIDs must be prefixed with this value.
164
+ */
165
+ uuid: string;
166
+ /** Plugin display name. */
167
+ name: string;
168
+ /** Author name shown on Marketplace. */
169
+ author: string;
170
+ /** Plugin description. */
171
+ description: string;
172
+ /** Path to plugin icon (extension omitted). 256×256 and 512×512 @2x. */
173
+ icon: string;
174
+ /**
175
+ * Plugin version.
176
+ * @example "1.0.0.0"
177
+ */
178
+ version: string;
179
+ /**
180
+ * Actions list group name.
181
+ * @default Same as `name`
182
+ */
183
+ category?: string;
184
+ /**
185
+ * Category icon path (extension omitted).
186
+ * @default Same as `icon`
187
+ */
188
+ categoryIcon?: string;
189
+ /** Plugin website URL. */
190
+ url?: string;
191
+ /** Support website URL. */
192
+ supportUrl?: string;
193
+ /** Global property inspector HTML path. */
194
+ propertyInspectorPath?: string;
195
+ /** Pre-defined profiles distributed with the plugin. */
196
+ profiles?: ManifestProfileInfo[];
197
+ /** Applications to monitor on Mac/Windows. */
198
+ applicationsToMonitor?: {
199
+ mac?: string[];
200
+ windows?: string[];
201
+ };
202
+ /**
203
+ * Default window size for `window.open()` from the property inspector.
204
+ * @example [500, 650]
205
+ */
206
+ defaultWindowSize?: [number, number];
207
+ /** macOS-specific entry point override. */
208
+ codePathMac?: string;
209
+ /** Windows-specific entry point override. */
210
+ codePathWin?: string;
211
+ /**
212
+ * Plugin entry point path.
213
+ * @default Derived from bundler output path (e.g. "bin/plugin.mjs")
214
+ */
215
+ codePath?: string;
216
+ /**
217
+ * Operating system requirements.
218
+ * @default [{ platform: "mac", minimumVersion: "13" }, { platform: "windows", minimumVersion: "10" }]
219
+ */
220
+ os?: [ManifestOSInfo, ManifestOSInfo?];
221
+ /**
222
+ * Node.js configuration.
223
+ * @default { version: "24" }
224
+ */
225
+ nodejs?: ManifestNodejsInfo;
226
+ /**
227
+ * SDK version.
228
+ * @default 2
229
+ */
230
+ sdkVersion?: 2 | 3;
231
+ /**
232
+ * Stream Deck software requirements.
233
+ * @default { minimumVersion: "7.1" }
234
+ */
235
+ software?: {
236
+ minimumVersion: string;
237
+ };
238
+ }
@@ -36,7 +36,7 @@ var RenderPool = class {
36
36
  }
37
37
  async doInitialize() {
38
38
  try {
39
- this.worker = new Worker(new URL("data:video/mp2t;base64,Ly8g4pSA4pSAIFJlbmRlciBXb3JrZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi8vCi8vIFJ1bnMgaW4gYSBzZXBhcmF0ZSB0aHJlYWQgdmlhIE5vZGUuanMgd29ya2VyX3RocmVhZHMuICBIYW5kbGVzIHRoZQovLyBmdWxsIHJlbmRlciBwaXBlbGluZTogc2VyaWFsaXplZCBWTm9kZSBkYXRhIOKGkiBUYWt1bWkgbm9kZXMg4oaSIHJhc3Rlci4KLy8KLy8gVXNlcyB0aGUgZGlyZWN0IFZOb2RlIOKGkiBUYWt1bWkgbm9kZSBieXBhc3MgKHNhbWUgYXMgbWFpbiB0aHJlYWQncwovLyB2bm9kZVRvVGFrdW1pTm9kZSBpbiBwaXBlbGluZS50cyksIHNraXBwaW5nIHZub2RlVG9FbGVtZW50KCkgYW5kCi8vIGZyb21Kc3goKSBlbnRpcmVseS4KLy8KLy8gVGhpcyB1bmJsb2NrcyB0aGUgbWFpbiB0aHJlYWQgZHVyaW5nIHRoZSBleHBlbnNpdmUgVGFrdW1pCi8vIHJhc3Rlcml6YXRpb24gc3RlcCAofjXigJMzMG1zIHBlciBmcmFtZSkuCi8vCi8vIFdoeSBjb2RlIGlzIGR1cGxpY2F0ZWQgKGlubGluZWQpOgovLyAgIFdvcmtlciB0aHJlYWRzIGNhbid0IGltcG9ydCBmcm9tIHRoZSBtYWluIGJ1bmRsZSDigJQgdGhleSBsb2FkCi8vICAgdGhlIGNvbXBpbGVkIHdvcmtlci5qcyBmaWxlIGluZGVwZW5kZW50bHkuICBTVkcgc2VyaWFsaXphdGlvbgovLyAgIGFuZCBWTm9kZeKGklRha3VtaSBjb252ZXJzaW9uIG11c3QgYmUgc2VsZi1jb250YWluZWQgaGVyZS4KLy8gICBCb3RoIG1pcnJvciB0aGUgbG9naWMgaW4gc3ZnLnRzIGFuZCBwaXBlbGluZS50cyByZXNwZWN0aXZlbHkuCi8vCi8vIFplcm8tY29weSByZXR1cm46Ci8vICAgVGhlIHJlbmRlcmVkIGJ1ZmZlciBpcyB0cmFuc2ZlcnJlZCAobm90IGNvcGllZCkgYmFjayB0byB0aGUgbWFpbgovLyAgIHRocmVhZCB2aWEgcG9zdE1lc3NhZ2UncyB0cmFuc2ZlciBsaXN0LiAgVGhpcyBhdm9pZHMgY29weWluZwovLyAgIHBvdGVudGlhbGx5IGxhcmdlIHJhc3RlciBidWZmZXJzIChlLmcuIDgwMMOXMTAww5c0ID0gMzIwS0IgZm9yCi8vICAgVG91Y2hTdHJpcCkgYWNyb3NzIHRoZSB0aHJlYWQgYm91bmRhcnkuCgppbXBvcnQgeyBwYXJlbnRQb3J0LCB3b3JrZXJEYXRhIH0gZnJvbSAibm9kZTp3b3JrZXJfdGhyZWFkcyI7CgovLyDilIDilIAgVHlwZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgppbnRlcmZhY2UgU2VyaWFsaXplZFZOb2RlIHsKICB0eXBlOiBzdHJpbmc7CiAgcHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+OwogIGNoaWxkcmVuOiBTZXJpYWxpemVkVk5vZGVbXTsKICB0ZXh0Pzogc3RyaW5nOwp9CgovKiogTWF0Y2hlcyBAdGFrdW1pLXJzL2hlbHBlcnMgTm9kZSB1bmlvbi4gUGxhaW4gb2JqZWN0IGFjY2VwdGVkIGJ5IFJlbmRlcmVyLnJlbmRlcigpLiAqLwppbnRlcmZhY2UgVGFrdW1pTm9kZSB7CiAgdHlwZTogc3RyaW5nOwogIFtrZXk6IHN0cmluZ106IHVua25vd247Cn0KCmludGVyZmFjZSBJbml0TWVzc2FnZSB7CiAgdHlwZTogImluaXQiOwogIGZvbnRzOiBBcnJheTx7CiAgICBuYW1lOiBzdHJpbmc7CiAgICBkYXRhOiBBcnJheUJ1ZmZlciB8IEJ1ZmZlcjsKICAgIHdlaWdodDogbnVtYmVyOwogICAgc3R5bGU6IHN0cmluZzsKICB9PjsKfQoKaW50ZXJmYWNlIFJlbmRlck1lc3NhZ2UgewogIHR5cGU6ICJyZW5kZXIiOwogIGlkOiBudW1iZXI7CiAgdm5vZGVzOiBTZXJpYWxpemVkVk5vZGVbXTsKICB3aWR0aDogbnVtYmVyOwogIGhlaWdodDogbnVtYmVyOwogIGZvcm1hdDogc3RyaW5nOwogIGRwcjogbnVtYmVyOwp9CgppbnRlcmZhY2UgU2h1dGRvd25NZXNzYWdlIHsKICB0eXBlOiAic2h1dGRvd24iOwp9Cgp0eXBlIFdvcmtlck1lc3NhZ2UgPSBJbml0TWVzc2FnZSB8IFJlbmRlck1lc3NhZ2UgfCBTaHV0ZG93bk1lc3NhZ2U7CgovLyDilIDilIAgU1ZHIFNlcmlhbGl6YXRpb24gKGlubGluZWQgZm9yIHdvcmtlciBjb250ZXh0KSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLy8gTWlycm9ycyB0aGUgc2VyaWFsaXplU3ZnVHJlZSgpIGZyb20gc3ZnLnRzLiBJbmxpbmVkIHRvIGF2b2lkCi8vIGNyb3NzLW1vZHVsZSBpbXBvcnQgaXNzdWVzIGluIHRoZSB3b3JrZXIgdGhyZWFkLgoKY29uc3QgU1ZHX0NBTUVMX0FUVFJTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldChbCiAgImFjY2VudEhlaWdodCIsCiAgImFsaWdubWVudEJhc2VsaW5lIiwKICAiYXJhYmljRm9ybSIsCiAgImJhc2VsaW5lU2hpZnQiLAogICJjYXBIZWlnaHQiLAogICJjbGlwUGF0aCIsCiAgImNsaXBQYXRoVW5pdHMiLAogICJjbGlwUnVsZSIsCiAgImNvbG9ySW50ZXJwb2xhdGlvbiIsCiAgImNvbG9ySW50ZXJwb2xhdGlvbkZpbHRlcnMiLAogICJjb2xvclByb2ZpbGUiLAogICJjb2xvclJlbmRlcmluZyIsCiAgImVuYWJsZUJhY2tncm91bmQiLAogICJmaWxsT3BhY2l0eSIsCiAgImZpbGxSdWxlIiwKICAiZmxvb2RDb2xvciIsCiAgImZsb29kT3BhY2l0eSIsCiAgImZvbnRGYW1pbHkiLAogICJmb250U2l6ZSIsCiAgImZvbnRTaXplQWRqdXN0IiwKICAiZm9udFN0cmV0Y2giLAogICJmb250U3R5bGUiLAogICJmb250VmFyaWFudCIsCiAgImZvbnRXZWlnaHQiLAogICJnbHlwaE5hbWUiLAogICJnbHlwaE9yaWVudGF0aW9uSG9yaXpvbnRhbCIsCiAgImdseXBoT3JpZW50YXRpb25WZXJ0aWNhbCIsCiAgImhvcml6QWR2WCIsCiAgImhvcml6T3JpZ2luWCIsCiAgImltYWdlUmVuZGVyaW5nIiwKICAibGV0dGVyU3BhY2luZyIsCiAgImxpZ2h0aW5nQ29sb3IiLAogICJtYXJrZXJFbmQiLAogICJtYXJrZXJNaWQiLAogICJtYXJrZXJTdGFydCIsCiAgIm92ZXJsaW5lUG9zaXRpb24iLAogICJvdmVybGluZVRoaWNrbmVzcyIsCiAgInBhaW50T3JkZXIiLAogICJwb2ludGVyRXZlbnRzIiwKICAicHJlc2VydmVBc3BlY3RSYXRpbyIsCiAgInNoYXBlUmVuZGVyaW5nIiwKICAic3RvcENvbG9yIiwKICAic3RvcE9wYWNpdHkiLAogICJzdHJva2VEYXNoYXJyYXkiLAogICJzdHJva2VEYXNob2Zmc2V0IiwKICAic3Ryb2tlTGluZWNhcCIsCiAgInN0cm9rZUxpbmVqb2luIiwKICAic3Ryb2tlTWl0ZXJsaW1pdCIsCiAgInN0cm9rZU9wYWNpdHkiLAogICJzdHJva2VXaWR0aCIsCiAgInRleHRBbmNob3IiLAogICJ0ZXh0RGVjb3JhdGlvbiIsCiAgInRleHRSZW5kZXJpbmciLAogICJ0cmFuc2Zvcm1PcmlnaW4iLAogICJ1bmRlcmxpbmVQb3NpdGlvbiIsCiAgInVuZGVybGluZVRoaWNrbmVzcyIsCiAgInVuaWNvZGVCaWRpIiwKICAidW5pY29kZVJhbmdlIiwKICAidW5pdHNQZXJFbSIsCiAgInZBbHBoYWJldGljIiwKICAidkhhbmdpbmciLAogICJ2SWRlb2dyYXBoaWMiLAogICJ2TWF0aGVtYXRpY2FsIiwKICAidmVjdG9yRWZmZWN0IiwKICAidmVydEFkdlkiLAogICJ2ZXJ0T3JpZ2luWCIsCiAgInZlcnRPcmlnaW5ZIiwKICAid29yZFNwYWNpbmciLAogICJ3cml0aW5nTW9kZSIsCl0pOwoKY29uc3QgU1ZHX1NLSVBfUFJPUFM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFsKICAiY2hpbGRyZW4iLAogICJrZXkiLAogICJyZWYiLAogICJfX3NlbGYiLAogICJfX3NvdXJjZSIsCl0pOwoKZnVuY3Rpb24gY2FtZWxUb0tlYmFiKHN0cjogc3RyaW5nKTogc3RyaW5nIHsKICByZXR1cm4gc3RyLnJlcGxhY2UoL1tBLVpdL2csIChjaCkgPT4gYC0ke2NoLnRvTG93ZXJDYXNlKCl9YCk7Cn0KCmZ1bmN0aW9uIGVzY2FwZUF0dHIodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7CiAgcmV0dXJuIHZhbHVlCiAgICAucmVwbGFjZSgvJi9nLCAiJmFtcDsiKQogICAgLnJlcGxhY2UoLyIvZywgIiZxdW90OyIpCiAgICAucmVwbGFjZSgvPC9nLCAiJmx0OyIpCiAgICAucmVwbGFjZSgvPi9nLCAiJmd0OyIpOwp9CgpmdW5jdGlvbiBzZXJpYWxpemVTdmdTdHlsZShzdHlsZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcgewogIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdOwogIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0eWxlKSkgewogICAgY29uc3QgdmFsdWUgPSBzdHlsZVtrZXldOwogICAgaWYgKHZhbHVlID09IG51bGwpIGNvbnRpbnVlOwogICAgcGFydHMucHVzaChgJHtjYW1lbFRvS2ViYWIoa2V5KX06JHtTdHJpbmcodmFsdWUpLnRyaW0oKX1gKTsKICB9CiAgcmV0dXJuIHBhcnRzLmpvaW4oIjsiKTsKfQoKZnVuY3Rpb24gc2VyaWFsaXplU3ZnQXR0cihrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCBudWxsIHsKICBpZiAoU1ZHX1NLSVBfUFJPUFMuaGFzKGtleSkgfHwgdmFsdWUgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgbGV0IGF0dHJOYW1lOiBzdHJpbmc7CiAgaWYgKGtleSA9PT0gImNsYXNzTmFtZSIpIGF0dHJOYW1lID0gImNsYXNzIjsKICBlbHNlIGlmIChTVkdfQ0FNRUxfQVRUUlMuaGFzKGtleSkpIGF0dHJOYW1lID0gY2FtZWxUb0tlYmFiKGtleSk7CiAgZWxzZSBhdHRyTmFtZSA9IGtleTsKICBpZiAoa2V5ID09PSAic3R5bGUiICYmIHR5cGVvZiB2YWx1ZSA9PT0gIm9iamVjdCIpIHsKICAgIGNvbnN0IGNzcyA9IHNlcmlhbGl6ZVN2Z1N0eWxlKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTsKICAgIGlmICghY3NzKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBgJHthdHRyTmFtZX09IiR7ZXNjYXBlQXR0cihjc3MpfSJgOwogIH0KICBpZiAodHlwZW9mIHZhbHVlID09PSAiYm9vbGVhbiIpIHJldHVybiBgJHthdHRyTmFtZX09IiR7U3RyaW5nKHZhbHVlKX0iYDsKICByZXR1cm4gYCR7YXR0ck5hbWV9PSIke2VzY2FwZUF0dHIoU3RyaW5nKHZhbHVlKSl9ImA7Cn0KCmZ1bmN0aW9uIHNlcmlhbGl6ZVN2Z1ZOb2RlKG5vZGU6IFNlcmlhbGl6ZWRWTm9kZSk6IHN0cmluZyB7CiAgaWYgKG5vZGUudHlwZSA9PT0gIiN0ZXh0IikgcmV0dXJuIG5vZGUudGV4dCA/PyAiIjsKICBjb25zdCBhdHRyczogc3RyaW5nW10gPSBbXTsKICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhub2RlLnByb3BzKSkgewogICAgY29uc3QgYXR0ciA9IHNlcmlhbGl6ZVN2Z0F0dHIoa2V5LCB2YWx1ZSk7CiAgICBpZiAoYXR0ciAhPSBudWxsKSBhdHRycy5wdXNoKGF0dHIpOwogIH0KICBjb25zdCBjaGlsZE1hcmt1cCA9IG5vZGUuY2hpbGRyZW4ubWFwKHNlcmlhbGl6ZVN2Z1ZOb2RlKS5qb2luKCIiKTsKICBjb25zdCBhdHRyU3RyID0gYXR0cnMubGVuZ3RoID4gMCA/IGAgJHthdHRycy5qb2luKCIgIil9YCA6ICIiOwogIHJldHVybiBgPCR7bm9kZS50eXBlfSR7YXR0clN0cn0+JHtjaGlsZE1hcmt1cH08LyR7bm9kZS50eXBlfT5gOwp9CgpmdW5jdGlvbiBzZXJpYWxpemVTdmdUcmVlKHN2Z05vZGU6IFNlcmlhbGl6ZWRWTm9kZSk6IHN0cmluZyB7CiAgaWYgKCEoInhtbG5zIiBpbiBzdmdOb2RlLnByb3BzKSkgewogICAgY29uc3QgYXVnbWVudGVkID0gewogICAgICAuLi5zdmdOb2RlLAogICAgICBwcm9wczogeyAuLi5zdmdOb2RlLnByb3BzLCB4bWxuczogImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB9LAogICAgfTsKICAgIHJldHVybiBzZXJpYWxpemVTdmdWTm9kZShhdWdtZW50ZWQpOwogIH0KICByZXR1cm4gc2VyaWFsaXplU3ZnVk5vZGUoc3ZnTm9kZSk7Cn0KCi8vIOKUgOKUgCBEaXJlY3QgVk5vZGUg4oaSIFRha3VtaSBOb2RlIENvbnZlcnNpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi8vIE1pcnJvcnMgdGhlIG1haW4tdGhyZWFkIHZub2RlVG9UYWt1bWlOb2RlKCkgZnJvbSBwaXBlbGluZS50cy4KLy8gSW5saW5lZCB0byBhdm9pZCBjcm9zcy1tb2R1bGUgaW1wb3J0IGlzc3VlcyBpbiB3b3JrZXIgY29udGV4dC4KCmZ1bmN0aW9uIHZub2RlVG9UYWt1bWlOb2RlKG5vZGU6IFNlcmlhbGl6ZWRWTm9kZSk6IFRha3VtaU5vZGUgewogIC8vIFRleHQgbm9kZXMg4oaSIFRha3VtaSBUZXh0Tm9kZQogIGlmIChub2RlLnR5cGUgPT09ICIjdGV4dCIpIHsKICAgIHJldHVybiB7IHR5cGU6ICJ0ZXh0IiwgdGV4dDogbm9kZS50ZXh0ID8/ICIiIH07CiAgfQoKICBjb25zdCB7IGNoaWxkcmVuOiBfY2hpbGRyZW4sIGNsYXNzTmFtZSwgc3JjLCAuLi5yZXN0UHJvcHMgfSA9IG5vZGUucHJvcHM7CgogIC8vIE1hcCBjbGFzc05hbWUg4oaSIHR3IChzYW1lIGxvZ2ljIGFzIG1haW4gdGhyZWFkKQogIGxldCB0dzogc3RyaW5nIHwgdW5kZWZpbmVkID0gdHlwZW9mIHJlc3RQcm9wcy50dyA9PT0gInN0cmluZyIgPyByZXN0UHJvcHMudHcgOiB1bmRlZmluZWQ7CiAgaWYgKHR5cGVvZiBjbGFzc05hbWUgPT09ICJzdHJpbmciICYmIGNsYXNzTmFtZS5sZW5ndGggPiAwKSB7CiAgICB0dyA9IHR3ID8gdHcgKyAiICIgKyBjbGFzc05hbWUgOiBjbGFzc05hbWU7CiAgfQoKICAvLyBJbWFnZSBub2RlcyDihpIgVGFrdW1pIEltYWdlTm9kZQogIGlmIChub2RlLnR5cGUgPT09ICJpbWciICYmIHR5cGVvZiBzcmMgPT09ICJzdHJpbmciKSB7CiAgICByZXR1cm4gewogICAgICB0eXBlOiAiaW1hZ2UiLAogICAgICBzcmM6IHNyYyBhcyBzdHJpbmcsCiAgICAgIC4uLih0dyA/IHsgdHcgfSA6IHt9KSwKICAgICAgLi4ucmVzdFByb3BzLAogICAgfTsKICB9CgogIC8vIFNWRyBub2RlcyDihpIgVGFrdW1pIEltYWdlTm9kZSAoc2VyaWFsaXplIHN1YnRyZWUgdG8gU1ZHIG1hcmt1cCkKICBpZiAobm9kZS50eXBlID09PSAic3ZnIikgewogICAgY29uc3Qgc3ZnTWFya3VwID0gc2VyaWFsaXplU3ZnVHJlZShub2RlKTsKICAgIGNvbnN0IHdpZHRoID0gdHlwZW9mIG5vZGUucHJvcHMud2lkdGggPT09ICJudW1iZXIiID8gbm9kZS5wcm9wcy53aWR0aCA6IHVuZGVmaW5lZDsKICAgIGNvbnN0IGhlaWdodCA9IHR5cGVvZiBub2RlLnByb3BzLmhlaWdodCA9PT0gIm51bWJlciIgPyBub2RlLnByb3BzLmhlaWdodCA6IHVuZGVmaW5lZDsKICAgIHJldHVybiB7CiAgICAgIHR5cGU6ICJpbWFnZSIsCiAgICAgIHNyYzogc3ZnTWFya3VwLAogICAgICAuLi4od2lkdGggIT0gbnVsbCA/IHsgd2lkdGggfSA6IHt9KSwKICAgICAgLi4uKGhlaWdodCAhPSBudWxsID8geyBoZWlnaHQgfSA6IHt9KSwKICAgICAgLi4uKHR3ID8geyB0dyB9IDoge30pLAogICAgICAuLi4obm9kZS5wcm9wcy5zdHlsZSA/IHsgc3R5bGU6IG5vZGUucHJvcHMuc3R5bGUgfSA6IHt9KSwKICAgICAgdGFnTmFtZTogInN2ZyIsCiAgICB9OwogIH0KCiAgLy8gQWxsIG90aGVyIG5vZGVzIOKGkiBUYWt1bWkgQ29udGFpbmVyTm9kZQogIGNvbnN0IHRha3VtaUNoaWxkcmVuID0KICAgIG5vZGUuY2hpbGRyZW4ubGVuZ3RoID4gMCA/IG5vZGUuY2hpbGRyZW4ubWFwKHZub2RlVG9UYWt1bWlOb2RlKSA6IHVuZGVmaW5lZDsKCiAgcmV0dXJuIHsKICAgIHR5cGU6ICJjb250YWluZXIiLAogICAgLi4uKHR3ID8geyB0dyB9IDoge30pLAogICAgLi4ucmVzdFByb3BzLAogICAgLi4uKHRha3VtaUNoaWxkcmVuID8geyBjaGlsZHJlbjogdGFrdW1pQ2hpbGRyZW4gfSA6IHt9KSwKICB9Owp9CgovLyDilIDilIAgUm9vdCBzdHlsZSBjb25zdGFudCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKCmNvbnN0IFJPT1RfU1RZTEUgPSB7IGRpc3BsYXk6ICJmbGV4Iiwgd2lkdGg6ICIxMDAlIiwgaGVpZ2h0OiAiMTAwJSIgfSBhcyBjb25zdDsKCi8vIOKUgOKUgCBXb3JrZXIgU3RhdGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgpsZXQgcmVuZGVyZXI6IGltcG9ydCgiQHRha3VtaS1ycy9jb3JlIikuUmVuZGVyZXIgfCBudWxsID0gbnVsbDsKCi8vIOKUgOKUgCBNZXNzYWdlIEhhbmRsZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgphc3luYyBmdW5jdGlvbiBoYW5kbGVNZXNzYWdlKG1zZzogV29ya2VyTWVzc2FnZSk6IFByb21pc2U8dm9pZD4gewogIHN3aXRjaCAobXNnLnR5cGUpIHsKICAgIGNhc2UgImluaXQiOiB7CiAgICAgIHRyeSB7CiAgICAgICAgLy8gRHluYW1pYyBpbXBvcnQg4oCUIG1heSBmYWlsIGlmIHRoZSBuYXRpdmUgYWRkb24gY2FuJ3QgbG9hZCBpbiBhIHdvcmtlcgogICAgICAgIGNvbnN0IGNvcmUgPSBhd2FpdCBpbXBvcnQoIkB0YWt1bWktcnMvY29yZSIpOwoKICAgICAgICByZW5kZXJlciA9IG5ldyBjb3JlLlJlbmRlcmVyKHsKICAgICAgICAgIGZvbnRzOiBtc2cuZm9udHMubWFwKChmKSA9PiAoewogICAgICAgICAgICBuYW1lOiBmLm5hbWUsCiAgICAgICAgICAgIGRhdGE6IGYuZGF0YSwKICAgICAgICAgICAgd2VpZ2h0OiBmLndlaWdodCBhcyAxMDAgfCAyMDAgfCAzMDAgfCA0MDAgfCA1MDAgfCA2MDAgfCA3MDAgfCA4MDAgfCA5MDAsCiAgICAgICAgICAgIHN0eWxlOiBmLnN0eWxlIGFzICJub3JtYWwiIHwgIml0YWxpYyIsCiAgICAgICAgICB9KSksCiAgICAgICAgfSk7CgogICAgICAgIHBhcmVudFBvcnQhLnBvc3RNZXNzYWdlKHsgdHlwZTogInJlYWR5IiB9KTsKICAgICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgICAgcGFyZW50UG9ydCEucG9zdE1lc3NhZ2UoewogICAgICAgICAgdHlwZTogImVycm9yIiwKICAgICAgICAgIGlkOiAtMSwKICAgICAgICAgIGVycm9yOiBgV29ya2VyIGluaXQgZmFpbGVkOiAke2VyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKX1gLAogICAgICAgIH0pOwogICAgICB9CiAgICAgIGJyZWFrOwogICAgfQoKICAgIGNhc2UgInJlbmRlciI6IHsKICAgICAgaWYgKHJlbmRlcmVyID09IG51bGwpIHsKICAgICAgICBwYXJlbnRQb3J0IS5wb3N0TWVzc2FnZSh7CiAgICAgICAgICB0eXBlOiAiZXJyb3IiLAogICAgICAgICAgaWQ6IG1zZy5pZCwKICAgICAgICAgIGVycm9yOiAiV29ya2VyIG5vdCBpbml0aWFsaXplZCIsCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0cnkgewogICAgICAgIC8vIDEuIENvbnZlcnQgc2VyaWFsaXplZCBWTm9kZSBkYXRhIOKGkiBUYWt1bWkgbm9kZXMgZGlyZWN0bHkgKGJ5cGFzcyBmcm9tSnN4KQogICAgICAgIGNvbnN0IGNoaWxkcmVuID0gbXNnLnZub2Rlcy5tYXAodm5vZGVUb1Rha3VtaU5vZGUpOwogICAgICAgIGNvbnN0IHJvb3ROb2RlOiBUYWt1bWlOb2RlID0gewogICAgICAgICAgdHlwZTogImNvbnRhaW5lciIsCiAgICAgICAgICBzdHlsZTogUk9PVF9TVFlMRSwKICAgICAgICAgIGNoaWxkcmVuLAogICAgICAgIH07CgogICAgICAgIC8vIDIuIFJlbmRlciB0byByYXN0ZXIgaW1hZ2UKICAgICAgICBjb25zdCBidWZmZXIgPSBhd2FpdCByZW5kZXJlci5yZW5kZXIocm9vdE5vZGUsIHsKICAgICAgICAgIHdpZHRoOiBtc2cud2lkdGgsCiAgICAgICAgICBoZWlnaHQ6IG1zZy5oZWlnaHQsCiAgICAgICAgICBmb3JtYXQ6IG1zZy5mb3JtYXQgYXMgaW1wb3J0KCJAdGFrdW1pLXJzL2NvcmUiKS5PdXRwdXRGb3JtYXQsCiAgICAgICAgICBkZXZpY2VQaXhlbFJhdGlvOiBtc2cuZHByLAogICAgICAgIH0pOwoKICAgICAgICAvLyBUcmFuc2ZlciB0aGUgYnVmZmVyICh6ZXJvLWNvcHkpIGJhY2sgdG8gdGhlIG1haW4gdGhyZWFkCiAgICAgICAgY29uc3QgYWIgPQogICAgICAgICAgYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIKICAgICAgICAgICAgPyBidWZmZXIKICAgICAgICAgICAgOiBidWZmZXIuYnVmZmVyLnNsaWNlKGJ1ZmZlci5ieXRlT2Zmc2V0LCBidWZmZXIuYnl0ZU9mZnNldCArIGJ1ZmZlci5ieXRlTGVuZ3RoKTsKCiAgICAgICAgcGFyZW50UG9ydCEucG9zdE1lc3NhZ2UoCiAgICAgICAgICB7IHR5cGU6ICJyZXN1bHQiLCBpZDogbXNnLmlkLCBidWZmZXI6IGFiIH0sCiAgICAgICAgICB7IHRyYW5zZmVyOiBbYWIgYXMgQXJyYXlCdWZmZXJdIH0sCiAgICAgICAgKTsKICAgICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgICAgcGFyZW50UG9ydCEucG9zdE1lc3NhZ2UoewogICAgICAgICAgdHlwZTogImVycm9yIiwKICAgICAgICAgIGlkOiBtc2cuaWQsCiAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLAogICAgICAgIH0pOwogICAgICB9CiAgICAgIGJyZWFrOwogICAgfQoKICAgIGNhc2UgInNodXRkb3duIjogewogICAgICBwcm9jZXNzLmV4aXQoMCk7CiAgICB9CiAgfQp9CgovLyDilIDilIAgQXV0by1pbml0IGlmIGZvbnRzIHByb3ZpZGVkIHZpYSB3b3JrZXJEYXRhIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAoKaWYgKHdvcmtlckRhdGE/LmZvbnRzKSB7CiAgaGFuZGxlTWVzc2FnZSh7IHR5cGU6ICJpbml0IiwgZm9udHM6IHdvcmtlckRhdGEuZm9udHMgfSk7Cn0KCnBhcmVudFBvcnQhLm9uKCJtZXNzYWdlIiwgKG1zZzogV29ya2VyTWVzc2FnZSkgPT4gewogIGhhbmRsZU1lc3NhZ2UobXNnKTsKfSk7Cg==", "" + import.meta.url), { workerData: { fonts: this.fonts.map((f) => ({
39
+ this.worker = new Worker(new URL("data:video/mp2t;base64,Ly8g4pSA4pSAIFJlbmRlciBXb3JrZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi8vCi8vIFJ1bnMgaW4gYSBzZXBhcmF0ZSB0aHJlYWQgdmlhIE5vZGUuanMgd29ya2VyX3RocmVhZHMuICBIYW5kbGVzIHRoZQovLyBmdWxsIHJlbmRlciBwaXBlbGluZTogc2VyaWFsaXplZCBWTm9kZSBkYXRhIOKGkiBUYWt1bWkgbm9kZXMg4oaSIHJhc3Rlci4KLy8KLy8gVXNlcyB0aGUgZGlyZWN0IFZOb2RlIOKGkiBUYWt1bWkgbm9kZSBieXBhc3MgKHNhbWUgYXMgbWFpbiB0aHJlYWQncwovLyB2bm9kZVRvVGFrdW1pTm9kZSBpbiBwaXBlbGluZS50cyksIHNraXBwaW5nIHZub2RlVG9FbGVtZW50KCkgYW5kCi8vIGZyb21Kc3goKSBlbnRpcmVseS4KLy8KLy8gVGhpcyB1bmJsb2NrcyB0aGUgbWFpbiB0aHJlYWQgZHVyaW5nIHRoZSBleHBlbnNpdmUgVGFrdW1pCi8vIHJhc3Rlcml6YXRpb24gc3RlcCAofjXigJMzMG1zIHBlciBmcmFtZSkuCi8vCi8vIFdoeSBjb2RlIGlzIGR1cGxpY2F0ZWQgKGlubGluZWQpOgovLyAgIFdvcmtlciB0aHJlYWRzIGNhbid0IGltcG9ydCBmcm9tIHRoZSBtYWluIGJ1bmRsZSDigJQgdGhleSBsb2FkCi8vICAgdGhlIGNvbXBpbGVkIHdvcmtlci5qcyBmaWxlIGluZGVwZW5kZW50bHkuICBTVkcgc2VyaWFsaXphdGlvbgovLyAgIGFuZCBWTm9kZeKGklRha3VtaSBjb252ZXJzaW9uIG11c3QgYmUgc2VsZi1jb250YWluZWQgaGVyZS4KLy8gICBCb3RoIG1pcnJvciB0aGUgbG9naWMgaW4gc3ZnLnRzIGFuZCBwaXBlbGluZS50cyByZXNwZWN0aXZlbHkuCi8vCi8vIFplcm8tY29weSByZXR1cm46Ci8vICAgVGhlIHJlbmRlcmVkIGJ1ZmZlciBpcyB0cmFuc2ZlcnJlZCAobm90IGNvcGllZCkgYmFjayB0byB0aGUgbWFpbgovLyAgIHRocmVhZCB2aWEgcG9zdE1lc3NhZ2UncyB0cmFuc2ZlciBsaXN0LiAgVGhpcyBhdm9pZHMgY29weWluZwovLyAgIHBvdGVudGlhbGx5IGxhcmdlIHJhc3RlciBidWZmZXJzIChlLmcuIDgwMMOXMTAww5c0ID0gMzIwS0IgZm9yCi8vICAgVG91Y2hTdHJpcCkgYWNyb3NzIHRoZSB0aHJlYWQgYm91bmRhcnkuCgppbXBvcnQgeyBwYXJlbnRQb3J0LCB3b3JrZXJEYXRhIH0gZnJvbSAibm9kZTp3b3JrZXJfdGhyZWFkcyI7CgovLyDilIDilIAgVHlwZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgppbnRlcmZhY2UgU2VyaWFsaXplZFZOb2RlIHsKICB0eXBlOiBzdHJpbmc7CiAgcHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+OwogIGNoaWxkcmVuOiBTZXJpYWxpemVkVk5vZGVbXTsKICB0ZXh0Pzogc3RyaW5nOwp9CgovKiogTWF0Y2hlcyBAdGFrdW1pLXJzL2hlbHBlcnMgTm9kZSB1bmlvbi4gUGxhaW4gb2JqZWN0IGFjY2VwdGVkIGJ5IFJlbmRlcmVyLnJlbmRlcigpLiAqLwppbnRlcmZhY2UgVGFrdW1pTm9kZSB7CiAgdHlwZTogc3RyaW5nOwogIFtrZXk6IHN0cmluZ106IHVua25vd247Cn0KCmludGVyZmFjZSBJbml0TWVzc2FnZSB7CiAgdHlwZTogImluaXQiOwogIGZvbnRzOiBBcnJheTx7CiAgICBuYW1lOiBzdHJpbmc7CiAgICBkYXRhOiBBcnJheUJ1ZmZlciB8IEJ1ZmZlcjsKICAgIHdlaWdodDogbnVtYmVyOwogICAgc3R5bGU6IHN0cmluZzsKICB9PjsKfQoKaW50ZXJmYWNlIFJlbmRlck1lc3NhZ2UgewogIHR5cGU6ICJyZW5kZXIiOwogIGlkOiBudW1iZXI7CiAgdm5vZGVzOiBTZXJpYWxpemVkVk5vZGVbXTsKICB3aWR0aDogbnVtYmVyOwogIGhlaWdodDogbnVtYmVyOwogIGZvcm1hdDogc3RyaW5nOwogIGRwcjogbnVtYmVyOwp9CgppbnRlcmZhY2UgU2h1dGRvd25NZXNzYWdlIHsKICB0eXBlOiAic2h1dGRvd24iOwp9Cgp0eXBlIFdvcmtlck1lc3NhZ2UgPSBJbml0TWVzc2FnZSB8IFJlbmRlck1lc3NhZ2UgfCBTaHV0ZG93bk1lc3NhZ2U7CgovLyDilIDilIAgU1ZHIFNlcmlhbGl6YXRpb24gKGlubGluZWQgZm9yIHdvcmtlciBjb250ZXh0KSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLy8gTWlycm9ycyB0aGUgc2VyaWFsaXplU3ZnVHJlZSgpIGZyb20gc3ZnLnRzLiBJbmxpbmVkIHRvIGF2b2lkCi8vIGNyb3NzLW1vZHVsZSBpbXBvcnQgaXNzdWVzIGluIHRoZSB3b3JrZXIgdGhyZWFkLgoKY29uc3QgU1ZHX0NBTUVMX0FUVFJTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldChbCiAgImFjY2VudEhlaWdodCIsCiAgImFsaWdubWVudEJhc2VsaW5lIiwKICAiYXJhYmljRm9ybSIsCiAgImJhc2VsaW5lU2hpZnQiLAogICJjYXBIZWlnaHQiLAogICJjbGlwUGF0aCIsCiAgImNsaXBQYXRoVW5pdHMiLAogICJjbGlwUnVsZSIsCiAgImNvbG9ySW50ZXJwb2xhdGlvbiIsCiAgImNvbG9ySW50ZXJwb2xhdGlvbkZpbHRlcnMiLAogICJjb2xvclByb2ZpbGUiLAogICJjb2xvclJlbmRlcmluZyIsCiAgImVuYWJsZUJhY2tncm91bmQiLAogICJmaWxsT3BhY2l0eSIsCiAgImZpbGxSdWxlIiwKICAiZmxvb2RDb2xvciIsCiAgImZsb29kT3BhY2l0eSIsCiAgImZvbnRGYW1pbHkiLAogICJmb250U2l6ZSIsCiAgImZvbnRTaXplQWRqdXN0IiwKICAiZm9udFN0cmV0Y2giLAogICJmb250U3R5bGUiLAogICJmb250VmFyaWFudCIsCiAgImZvbnRXZWlnaHQiLAogICJnbHlwaE5hbWUiLAogICJnbHlwaE9yaWVudGF0aW9uSG9yaXpvbnRhbCIsCiAgImdseXBoT3JpZW50YXRpb25WZXJ0aWNhbCIsCiAgImhvcml6QWR2WCIsCiAgImhvcml6T3JpZ2luWCIsCiAgImltYWdlUmVuZGVyaW5nIiwKICAibGV0dGVyU3BhY2luZyIsCiAgImxpZ2h0aW5nQ29sb3IiLAogICJtYXJrZXJFbmQiLAogICJtYXJrZXJNaWQiLAogICJtYXJrZXJTdGFydCIsCiAgIm92ZXJsaW5lUG9zaXRpb24iLAogICJvdmVybGluZVRoaWNrbmVzcyIsCiAgInBhaW50T3JkZXIiLAogICJwb2ludGVyRXZlbnRzIiwKICAicHJlc2VydmVBc3BlY3RSYXRpbyIsCiAgInNoYXBlUmVuZGVyaW5nIiwKICAic3RvcENvbG9yIiwKICAic3RvcE9wYWNpdHkiLAogICJzdHJva2VEYXNoYXJyYXkiLAogICJzdHJva2VEYXNob2Zmc2V0IiwKICAic3Ryb2tlTGluZWNhcCIsCiAgInN0cm9rZUxpbmVqb2luIiwKICAic3Ryb2tlTWl0ZXJsaW1pdCIsCiAgInN0cm9rZU9wYWNpdHkiLAogICJzdHJva2VXaWR0aCIsCiAgInRleHRBbmNob3IiLAogICJ0ZXh0RGVjb3JhdGlvbiIsCiAgInRleHRSZW5kZXJpbmciLAogICJ0cmFuc2Zvcm1PcmlnaW4iLAogICJ1bmRlcmxpbmVQb3NpdGlvbiIsCiAgInVuZGVybGluZVRoaWNrbmVzcyIsCiAgInVuaWNvZGVCaWRpIiwKICAidW5pY29kZVJhbmdlIiwKICAidW5pdHNQZXJFbSIsCiAgInZBbHBoYWJldGljIiwKICAidkhhbmdpbmciLAogICJ2SWRlb2dyYXBoaWMiLAogICJ2TWF0aGVtYXRpY2FsIiwKICAidmVjdG9yRWZmZWN0IiwKICAidmVydEFkdlkiLAogICJ2ZXJ0T3JpZ2luWCIsCiAgInZlcnRPcmlnaW5ZIiwKICAid29yZFNwYWNpbmciLAogICJ3cml0aW5nTW9kZSIsCl0pOwoKY29uc3QgU1ZHX1NLSVBfUFJPUFM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFsKICAiY2hpbGRyZW4iLAogICJrZXkiLAogICJyZWYiLAogICJfX3NlbGYiLAogICJfX3NvdXJjZSIsCl0pOwoKZnVuY3Rpb24gY2FtZWxUb0tlYmFiKHN0cjogc3RyaW5nKTogc3RyaW5nIHsKICByZXR1cm4gc3RyLnJlcGxhY2UoL1tBLVpdL2csIChjaCkgPT4gYC0ke2NoLnRvTG93ZXJDYXNlKCl9YCk7Cn0KCmZ1bmN0aW9uIGVzY2FwZUF0dHIodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7CiAgcmV0dXJuIHZhbHVlCiAgICAucmVwbGFjZSgvJi9nLCAiJmFtcDsiKQogICAgLnJlcGxhY2UoLyIvZywgIiZxdW90OyIpCiAgICAucmVwbGFjZSgvPC9nLCAiJmx0OyIpCiAgICAucmVwbGFjZSgvPi9nLCAiJmd0OyIpOwp9CgpmdW5jdGlvbiBzZXJpYWxpemVTdmdTdHlsZShzdHlsZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcgewogIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdOwogIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0eWxlKSkgewogICAgY29uc3QgdmFsdWUgPSBzdHlsZVtrZXldOwogICAgaWYgKHZhbHVlID09IG51bGwpIGNvbnRpbnVlOwogICAgcGFydHMucHVzaChgJHtjYW1lbFRvS2ViYWIoa2V5KX06JHtTdHJpbmcodmFsdWUpLnRyaW0oKX1gKTsKICB9CiAgcmV0dXJuIHBhcnRzLmpvaW4oIjsiKTsKfQoKZnVuY3Rpb24gc2VyaWFsaXplU3ZnQXR0cihrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCBudWxsIHsKICBpZiAoU1ZHX1NLSVBfUFJPUFMuaGFzKGtleSkgfHwgdmFsdWUgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgbGV0IGF0dHJOYW1lOiBzdHJpbmc7CiAgaWYgKGtleSA9PT0gImNsYXNzTmFtZSIpIGF0dHJOYW1lID0gImNsYXNzIjsKICBlbHNlIGlmIChTVkdfQ0FNRUxfQVRUUlMuaGFzKGtleSkpIGF0dHJOYW1lID0gY2FtZWxUb0tlYmFiKGtleSk7CiAgZWxzZSBhdHRyTmFtZSA9IGtleTsKICBpZiAoa2V5ID09PSAic3R5bGUiICYmIHR5cGVvZiB2YWx1ZSA9PT0gIm9iamVjdCIpIHsKICAgIGNvbnN0IGNzcyA9IHNlcmlhbGl6ZVN2Z1N0eWxlKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTsKICAgIGlmICghY3NzKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBgJHthdHRyTmFtZX09IiR7ZXNjYXBlQXR0cihjc3MpfSJgOwogIH0KICBpZiAodHlwZW9mIHZhbHVlID09PSAiYm9vbGVhbiIpIHJldHVybiBgJHthdHRyTmFtZX09IiR7U3RyaW5nKHZhbHVlKX0iYDsKICByZXR1cm4gYCR7YXR0ck5hbWV9PSIke2VzY2FwZUF0dHIoU3RyaW5nKHZhbHVlKSl9ImA7Cn0KCmZ1bmN0aW9uIHNlcmlhbGl6ZVN2Z1ZOb2RlKG5vZGU6IFNlcmlhbGl6ZWRWTm9kZSk6IHN0cmluZyB7CiAgaWYgKG5vZGUudHlwZSA9PT0gIiN0ZXh0IikgcmV0dXJuIG5vZGUudGV4dCA/PyAiIjsKICBjb25zdCBhdHRyczogc3RyaW5nW10gPSBbXTsKICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhub2RlLnByb3BzKSkgewogICAgY29uc3QgYXR0ciA9IHNlcmlhbGl6ZVN2Z0F0dHIoa2V5LCB2YWx1ZSk7CiAgICBpZiAoYXR0ciAhPSBudWxsKSBhdHRycy5wdXNoKGF0dHIpOwogIH0KICBjb25zdCBjaGlsZE1hcmt1cCA9IG5vZGUuY2hpbGRyZW4ubWFwKHNlcmlhbGl6ZVN2Z1ZOb2RlKS5qb2luKCIiKTsKICBjb25zdCBhdHRyU3RyID0gYXR0cnMubGVuZ3RoID4gMCA/IGAgJHthdHRycy5qb2luKCIgIil9YCA6ICIiOwogIHJldHVybiBgPCR7bm9kZS50eXBlfSR7YXR0clN0cn0+JHtjaGlsZE1hcmt1cH08LyR7bm9kZS50eXBlfT5gOwp9CgpmdW5jdGlvbiBzZXJpYWxpemVTdmdUcmVlKHN2Z05vZGU6IFNlcmlhbGl6ZWRWTm9kZSk6IHN0cmluZyB7CiAgaWYgKCEoInhtbG5zIiBpbiBzdmdOb2RlLnByb3BzKSkgewogICAgY29uc3QgYXVnbWVudGVkID0gewogICAgICAuLi5zdmdOb2RlLAogICAgICBwcm9wczogeyAuLi5zdmdOb2RlLnByb3BzLCB4bWxuczogImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB9LAogICAgfTsKICAgIHJldHVybiBzZXJpYWxpemVTdmdWTm9kZShhdWdtZW50ZWQpOwogIH0KICByZXR1cm4gc2VyaWFsaXplU3ZnVk5vZGUoc3ZnTm9kZSk7Cn0KCi8vIOKUgOKUgCBEaXJlY3QgVk5vZGUg4oaSIFRha3VtaSBOb2RlIENvbnZlcnNpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi8vIE1pcnJvcnMgdGhlIG1haW4tdGhyZWFkIHZub2RlVG9UYWt1bWlOb2RlKCkgZnJvbSBwaXBlbGluZS50cy4KLy8gSW5saW5lZCB0byBhdm9pZCBjcm9zcy1tb2R1bGUgaW1wb3J0IGlzc3VlcyBpbiB3b3JrZXIgY29udGV4dC4KCmZ1bmN0aW9uIHZub2RlVG9UYWt1bWlOb2RlKG5vZGU6IFNlcmlhbGl6ZWRWTm9kZSk6IFRha3VtaU5vZGUgewogIC8vIFRleHQgbm9kZXMg4oaSIFRha3VtaSBUZXh0Tm9kZQogIGlmIChub2RlLnR5cGUgPT09ICIjdGV4dCIpIHsKICAgIHJldHVybiB7IHR5cGU6ICJ0ZXh0IiwgdGV4dDogbm9kZS50ZXh0ID8/ICIiIH07CiAgfQoKICBjb25zdCB7IGNoaWxkcmVuOiBfY2hpbGRyZW4sIGNsYXNzTmFtZSwgc3JjLCAuLi5yZXN0UHJvcHMgfSA9IG5vZGUucHJvcHM7CgogIC8vIE1hcCBjbGFzc05hbWUg4oaSIHR3IChzYW1lIGxvZ2ljIGFzIG1haW4gdGhyZWFkKQogIGxldCB0dzogc3RyaW5nIHwgdW5kZWZpbmVkID0gdHlwZW9mIHJlc3RQcm9wcy50dyA9PT0gInN0cmluZyIgPyByZXN0UHJvcHMudHcgOiB1bmRlZmluZWQ7CiAgaWYgKHR5cGVvZiBjbGFzc05hbWUgPT09ICJzdHJpbmciICYmIGNsYXNzTmFtZS5sZW5ndGggPiAwKSB7CiAgICB0dyA9IHR3ID8gdHcgKyAiICIgKyBjbGFzc05hbWUgOiBjbGFzc05hbWU7CiAgfQoKICAvLyBJbWFnZSBub2RlcyDihpIgVGFrdW1pIEltYWdlTm9kZQogIGlmIChub2RlLnR5cGUgPT09ICJpbWciICYmIHR5cGVvZiBzcmMgPT09ICJzdHJpbmciKSB7CiAgICByZXR1cm4gewogICAgICB0eXBlOiAiaW1hZ2UiLAogICAgICBzcmM6IHNyYyBhcyBzdHJpbmcsCiAgICAgIC4uLih0dyA/IHsgdHcgfSA6IHt9KSwKICAgICAgLi4ucmVzdFByb3BzLAogICAgfTsKICB9CgogIC8vIFNWRyBub2RlcyDihpIgVGFrdW1pIEltYWdlTm9kZSAoc2VyaWFsaXplIHN1YnRyZWUgdG8gU1ZHIG1hcmt1cCkKICBpZiAobm9kZS50eXBlID09PSAic3ZnIikgewogICAgY29uc3Qgc3ZnTWFya3VwID0gc2VyaWFsaXplU3ZnVHJlZShub2RlKTsKICAgIGNvbnN0IHdpZHRoID0gdHlwZW9mIG5vZGUucHJvcHMud2lkdGggPT09ICJudW1iZXIiID8gbm9kZS5wcm9wcy53aWR0aCA6IHVuZGVmaW5lZDsKICAgIGNvbnN0IGhlaWdodCA9IHR5cGVvZiBub2RlLnByb3BzLmhlaWdodCA9PT0gIm51bWJlciIgPyBub2RlLnByb3BzLmhlaWdodCA6IHVuZGVmaW5lZDsKICAgIHJldHVybiB7CiAgICAgIHR5cGU6ICJpbWFnZSIsCiAgICAgIHNyYzogc3ZnTWFya3VwLAogICAgICAuLi4od2lkdGggIT0gbnVsbCA/IHsgd2lkdGggfSA6IHt9KSwKICAgICAgLi4uKGhlaWdodCAhPSBudWxsID8geyBoZWlnaHQgfSA6IHt9KSwKICAgICAgLi4uKHR3ID8geyB0dyB9IDoge30pLAogICAgICAuLi4obm9kZS5wcm9wcy5zdHlsZSA/IHsgc3R5bGU6IG5vZGUucHJvcHMuc3R5bGUgfSA6IHt9KSwKICAgICAgdGFnTmFtZTogInN2ZyIsCiAgICB9OwogIH0KCiAgLy8gQWxsIG90aGVyIG5vZGVzIOKGkiBUYWt1bWkgQ29udGFpbmVyTm9kZQogIGNvbnN0IHRha3VtaUNoaWxkcmVuID0KICAgIG5vZGUuY2hpbGRyZW4ubGVuZ3RoID4gMCA/IG5vZGUuY2hpbGRyZW4ubWFwKHZub2RlVG9UYWt1bWlOb2RlKSA6IHVuZGVmaW5lZDsKCiAgcmV0dXJuIHsKICAgIHR5cGU6ICJjb250YWluZXIiLAogICAgLi4uKHR3ID8geyB0dyB9IDoge30pLAogICAgLi4ucmVzdFByb3BzLAogICAgLi4uKHRha3VtaUNoaWxkcmVuID8geyBjaGlsZHJlbjogdGFrdW1pQ2hpbGRyZW4gfSA6IHt9KSwKICB9Owp9CgovLyDilIDilIAgUm9vdCBzdHlsZSBjb25zdGFudCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKCmNvbnN0IFJPT1RfU1RZTEUgPSB7IGRpc3BsYXk6ICJmbGV4Iiwgd2lkdGg6ICIxMDAlIiwgaGVpZ2h0OiAiMTAwJSIgfSBhcyBjb25zdDsKCi8vIOKUgOKUgCBXb3JrZXIgU3RhdGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgpsZXQgcmVuZGVyZXI6IGltcG9ydCgiQHRha3VtaS1ycy9jb3JlIikuUmVuZGVyZXIgfCBudWxsID0gbnVsbDsKCi8vIOKUgOKUgCBNZXNzYWdlIEhhbmRsZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgphc3luYyBmdW5jdGlvbiBoYW5kbGVNZXNzYWdlKG1zZzogV29ya2VyTWVzc2FnZSk6IFByb21pc2U8dm9pZD4gewogIHN3aXRjaCAobXNnLnR5cGUpIHsKICAgIGNhc2UgImluaXQiOiB7CiAgICAgIHRyeSB7CiAgICAgICAgLy8gRHluYW1pYyBpbXBvcnQg4oCUIG1heSBmYWlsIGlmIHRoZSBuYXRpdmUgYWRkb24gY2FuJ3QgbG9hZCBpbiBhIHdvcmtlcgogICAgICAgIGNvbnN0IGNvcmUgPSBhd2FpdCBpbXBvcnQoIkB0YWt1bWktcnMvY29yZSIpOwoKICAgICAgICByZW5kZXJlciA9IG5ldyBjb3JlLlJlbmRlcmVyKHsKICAgICAgICAgIGZvbnRzOiBtc2cuZm9udHMubWFwKChmKSA9PiAoewogICAgICAgICAgICBuYW1lOiBmLm5hbWUsCiAgICAgICAgICAgIGRhdGE6IGYuZGF0YSwKICAgICAgICAgICAgd2VpZ2h0OiBmLndlaWdodCBhcyAxMDAgfCAyMDAgfCAzMDAgfCA0MDAgfCA1MDAgfCA2MDAgfCA3MDAgfCA4MDAgfCA5MDAsCiAgICAgICAgICAgIHN0eWxlOiBmLnN0eWxlIGFzICJub3JtYWwiIHwgIml0YWxpYyIsCiAgICAgICAgICB9KSksCiAgICAgICAgfSk7CgogICAgICAgIHBhcmVudFBvcnQhLnBvc3RNZXNzYWdlKHsgdHlwZTogInJlYWR5IiB9KTsKICAgICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgICAgcGFyZW50UG9ydCEucG9zdE1lc3NhZ2UoewogICAgICAgICAgdHlwZTogImVycm9yIiwKICAgICAgICAgIGlkOiAtMSwKICAgICAgICAgIGVycm9yOiBgV29ya2VyIGluaXQgZmFpbGVkOiAke2VyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKX1gLAogICAgICAgIH0pOwogICAgICB9CiAgICAgIGJyZWFrOwogICAgfQoKICAgIGNhc2UgInJlbmRlciI6IHsKICAgICAgaWYgKHJlbmRlcmVyID09IG51bGwpIHsKICAgICAgICBwYXJlbnRQb3J0IS5wb3N0TWVzc2FnZSh7CiAgICAgICAgICB0eXBlOiAiZXJyb3IiLAogICAgICAgICAgaWQ6IG1zZy5pZCwKICAgICAgICAgIGVycm9yOiAiV29ya2VyIG5vdCBpbml0aWFsaXplZCIsCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CgogICAgICB0cnkgewogICAgICAgIC8vIDEuIENvbnZlcnQgc2VyaWFsaXplZCBWTm9kZSBkYXRhIOKGkiBUYWt1bWkgbm9kZXMgZGlyZWN0bHkgKGJ5cGFzcyBmcm9tSnN4KQogICAgICAgIGNvbnN0IGNoaWxkcmVuID0gbXNnLnZub2Rlcy5tYXAodm5vZGVUb1Rha3VtaU5vZGUpOwogICAgICAgIGNvbnN0IHJvb3ROb2RlOiBUYWt1bWlOb2RlID0gewogICAgICAgICAgdHlwZTogImNvbnRhaW5lciIsCiAgICAgICAgICBzdHlsZTogUk9PVF9TVFlMRSwKICAgICAgICAgIGNoaWxkcmVuLAogICAgICAgIH07CgogICAgICAgIC8vIDIuIFJlbmRlciB0byByYXN0ZXIgaW1hZ2UKICAgICAgICAvLyBDYXN0OiBUYWt1bWlOb2RlIGlzIGEgbG9jYWwgc3RydWN0dXJhbCBkdXBsaWNhdGUgb2YgdGhlCiAgICAgICAgLy8gQHRha3VtaS1ycy9oZWxwZXJzIE5vZGUgdW5pb24g4oCUIHRoZSBzaGFwZXMgbWF0Y2ggYXQgcnVudGltZQogICAgICAgIC8vIGJ1dCBUeXBlU2NyaXB0IGNhbid0IHZlcmlmeSB0aGUgZGlzY3JpbWluYXRlZCB1bmlvbiBtZW1iZXJzCiAgICAgICAgLy8gZnJvbSB0aGUgbG9vc2UgYHR5cGU6IHN0cmluZ2AgaW5kZXggc2lnbmF0dXJlLgogICAgICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IHJlbmRlcmVyLnJlbmRlcigKICAgICAgICAgIHJvb3ROb2RlIGFzIHVua25vd24gYXMgaW1wb3J0KCJAdGFrdW1pLXJzL2hlbHBlcnMiKS5Ob2RlLAogICAgICAgICAgewogICAgICAgICAgICB3aWR0aDogbXNnLndpZHRoLAogICAgICAgICAgICBoZWlnaHQ6IG1zZy5oZWlnaHQsCiAgICAgICAgICAgIGZvcm1hdDogbXNnLmZvcm1hdCBhcyBpbXBvcnQoIkB0YWt1bWktcnMvY29yZSIpLk91dHB1dEZvcm1hdCwKICAgICAgICAgICAgZGV2aWNlUGl4ZWxSYXRpbzogbXNnLmRwciwKICAgICAgICAgIH0sCiAgICAgICAgKTsKCiAgICAgICAgLy8gVHJhbnNmZXIgdGhlIGJ1ZmZlciAoemVyby1jb3B5KSBiYWNrIHRvIHRoZSBtYWluIHRocmVhZAogICAgICAgIGNvbnN0IGFiID0KICAgICAgICAgIGJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyCiAgICAgICAgICAgID8gYnVmZmVyCiAgICAgICAgICAgIDogYnVmZmVyLmJ1ZmZlci5zbGljZShidWZmZXIuYnl0ZU9mZnNldCwgYnVmZmVyLmJ5dGVPZmZzZXQgKyBidWZmZXIuYnl0ZUxlbmd0aCk7CgogICAgICAgIHBhcmVudFBvcnQhLnBvc3RNZXNzYWdlKAogICAgICAgICAgeyB0eXBlOiAicmVzdWx0IiwgaWQ6IG1zZy5pZCwgYnVmZmVyOiBhYiB9LAogICAgICAgICAgeyB0cmFuc2ZlcjogW2FiIGFzIEFycmF5QnVmZmVyXSB9LAogICAgICAgICk7CiAgICAgIH0gY2F0Y2ggKGVycikgewogICAgICAgIHBhcmVudFBvcnQhLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHR5cGU6ICJlcnJvciIsCiAgICAgICAgICBpZDogbXNnLmlkLAogICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSwKICAgICAgICB9KTsKICAgICAgfQogICAgICBicmVhazsKICAgIH0KCiAgICBjYXNlICJzaHV0ZG93biI6IHsKICAgICAgcHJvY2Vzcy5leGl0KDApOwogICAgfQogIH0KfQoKLy8g4pSA4pSAIEF1dG8taW5pdCBpZiBmb250cyBwcm92aWRlZCB2aWEgd29ya2VyRGF0YSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKCmlmICh3b3JrZXJEYXRhPy5mb250cykgewogIGhhbmRsZU1lc3NhZ2UoeyB0eXBlOiAiaW5pdCIsIGZvbnRzOiB3b3JrZXJEYXRhLmZvbnRzIH0pOwp9CgpwYXJlbnRQb3J0IS5vbigibWVzc2FnZSIsIChtc2c6IFdvcmtlck1lc3NhZ2UpID0+IHsKICBoYW5kbGVNZXNzYWdlKG1zZyk7Cn0pOwo=", "" + import.meta.url), { workerData: { fonts: this.fonts.map((f) => ({
40
40
  name: f.name,
41
41
  data: f.data,
42
42
  weight: f.weight,
package/dist/rollup.d.ts CHANGED
@@ -1,14 +1,42 @@
1
1
  import { Plugin } from 'rollup';
2
2
  import { StreamDeckTargetOptions } from './bundler-shared';
3
+ import { PluginManifestInfo } from './manifest-types';
3
4
  export type { StreamDeckPlatform, StreamDeckArch, StreamDeckTarget, StreamDeckTargetOptions, TakumiBackend, } from './bundler-shared';
5
+ export type { ManifestActionSource, PluginManifestInfo, ActionManifestInfo, ManifestController, ManifestEncoderInfo, ManifestTriggerDescription, ManifestStateInfo, ManifestOSInfo, ManifestNodejsInfo, ManifestProfileInfo, } from './manifest-types';
4
6
  export interface StreamDeckRollupOptions extends StreamDeckTargetOptions {
5
7
  /**
6
- * Path to the plugin `manifest.json`. When omitted, the plugin
7
- * auto-detects by scanning the project root for a `*.sdPlugin/manifest.json`.
8
+ * Code-first manifest generation. When a `PluginManifestInfo` object
9
+ * is provided, the plugin generates `manifest.json` in the `.sdPlugin`
10
+ * directory during `writeBundle`.
8
11
  *
9
- * Set to `false` to disable manifest type generation entirely.
12
+ * Actions are **auto-extracted** from `defineAction()` calls in the
13
+ * source code — no need to list them here. The plugin scans the
14
+ * module graph during the build and extracts `uuid`, `info`, and
15
+ * component presence from each `defineAction()` call.
16
+ *
17
+ * Actions with `info.disabled: true` are skipped.
18
+ *
19
+ * Auto-derived defaults:
20
+ * - `CodePath` from the bundler output path
21
+ * - `Controllers` from key/dial/touchStrip presence
22
+ * - `OS`, `Nodejs`, `SDKVersion`, `Software` have defaults
23
+ * - `States` default to `[{ Image: icon }]`
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * streamDeckReact({
28
+ * manifest: {
29
+ * uuid: "com.example.my-plugin",
30
+ * name: "My Plugin",
31
+ * author: "Me",
32
+ * description: "A plugin",
33
+ * icon: "imgs/plugin-icon",
34
+ * version: "1.0.0.0",
35
+ * },
36
+ * })
37
+ * ```
10
38
  */
11
- manifest?: string | false;
39
+ manifest?: PluginManifestInfo;
12
40
  }
13
41
  /**
14
42
  * Rollup plugin for Stream Deck React projects.
@@ -19,12 +47,11 @@ export interface StreamDeckRollupOptions extends StreamDeckTargetOptions {
19
47
  * - No `configResolved` — dev mode detected via `this.meta.watchMode`
20
48
  * - `onLog` suppresses `MODULE_LEVEL_DIRECTIVE` warnings (caused by
21
49
  * "use client" directives in React dependencies)
22
- * - `buildStart` resolves root via `resolve(".")` (no Vite config)
23
- * - `writeBundle` reads output dir from `outputOptions.dir` or
24
- * `dirname(outputOptions.file)` (Rollup supports both)
50
+ * - `moduleParsed` extracts defineAction() metadata from each module
51
+ * - `writeBundle` generates manifest.json + copies native bindings
25
52
  * - No `closeBundle` restart hook (handled externally)
26
53
  *
27
- * Font inlining and manifest codegen are shared via bundler-shared.ts,
28
- * font-inline.ts, and manifest-codegen.ts.
54
+ * Font inlining and manifest generation are shared via bundler-shared.ts,
55
+ * font-inline.ts, manifest-gen.ts, and manifest-extract.ts.
29
56
  */
30
57
  export declare function streamDeckReact(options?: StreamDeckRollupOptions): Plugin;
package/dist/rollup.js CHANGED
@@ -1,7 +1,8 @@
1
- import { NOOP_DEVTOOLS_CODE, NOOP_DEVTOOLS_ID, TAKUMI_NATIVE_LOADER_CODE, TAKUMI_NATIVE_LOADER_ID, copyNativeBindings, isDevelopmentMode, isLibraryDevtoolsImport, shouldStripDevtools } from "./bundler-shared.js";
1
+ import { NOOP_DEVTOOLS_CODE, NOOP_DEVTOOLS_ID, TAKUMI_NATIVE_LOADER_CODE, TAKUMI_NATIVE_LOADER_ID, copyNativeBindings, deriveCodePath, isDevelopmentMode, isLibraryDevtoolsImport, resolvePluginDir, shouldStripDevtools } from "./bundler-shared.js";
2
2
  import { loadFont, resolveFontId } from "./font-inline.js";
3
- import { generateManifestTypes } from "./manifest-codegen.js";
4
- import { dirname, resolve } from "node:path";
3
+ import { generateManifestJsonString, validateManifestConfig, validatePluginUUID, writeManifestIfChanged } from "./manifest-gen.js";
4
+ import { extractActionsFromAST, extractedToActionSource } from "./manifest-extract.js";
5
+ import { dirname, join } from "node:path";
5
6
  //#region src/rollup.ts
6
7
  /**
7
8
  * Rollup plugin for Stream Deck React projects.
@@ -12,28 +13,37 @@ import { dirname, resolve } from "node:path";
12
13
  * - No `configResolved` — dev mode detected via `this.meta.watchMode`
13
14
  * - `onLog` suppresses `MODULE_LEVEL_DIRECTIVE` warnings (caused by
14
15
  * "use client" directives in React dependencies)
15
- * - `buildStart` resolves root via `resolve(".")` (no Vite config)
16
- * - `writeBundle` reads output dir from `outputOptions.dir` or
17
- * `dirname(outputOptions.file)` (Rollup supports both)
16
+ * - `moduleParsed` extracts defineAction() metadata from each module
17
+ * - `writeBundle` generates manifest.json + copies native bindings
18
18
  * - No `closeBundle` restart hook (handled externally)
19
19
  *
20
- * Font inlining and manifest codegen are shared via bundler-shared.ts,
21
- * font-inline.ts, and manifest-codegen.ts.
20
+ * Font inlining and manifest generation are shared via bundler-shared.ts,
21
+ * font-inline.ts, manifest-gen.ts, and manifest-extract.ts.
22
22
  */
23
23
  function streamDeckReact(options = {}) {
24
+ const extractedActions = [];
24
25
  return {
25
26
  name: "fcannizzaro-streamdeck-react",
26
27
  onLog(_level, log) {
27
28
  if (log.code === "MODULE_LEVEL_DIRECTIVE") return false;
28
29
  },
29
30
  buildStart() {
30
- const root = resolve(".");
31
- const warn = (msg) => this.warn(msg);
32
- const result = generateManifestTypes(root, options.manifest, warn);
33
- if (result) {
34
- this.addWatchFile(result.manifestPath);
35
- if (result.written) console.log("[@fcannizzaro/streamdeck-react] Generated src/streamdeck-env.d.ts");
31
+ if (options.manifest) {
32
+ const uuidError = validatePluginUUID(options.manifest.uuid);
33
+ if (uuidError) this.warn(`[@fcannizzaro/streamdeck-react] ${uuidError.message}`);
36
34
  }
35
+ extractedActions.length = 0;
36
+ },
37
+ moduleParsed(moduleInfo) {
38
+ if (!options.manifest) return;
39
+ if (!moduleInfo.code?.includes("defineAction")) return;
40
+ try {
41
+ const actions = extractActionsFromAST(this.parse(moduleInfo.code));
42
+ for (const action of actions) {
43
+ if (action.info?.disabled) continue;
44
+ extractedActions.push(action);
45
+ }
46
+ } catch {}
37
47
  },
38
48
  resolveId: {
39
49
  order: "pre",
@@ -56,6 +66,23 @@ function streamDeckReact(options = {}) {
56
66
  const outDir = outputOptions.file ? dirname(outputOptions.file) : outputOptions.dir;
57
67
  if (!outDir) return;
58
68
  copyNativeBindings(outDir, isDevelopment, options, (msg) => this.warn(msg));
69
+ if (options.manifest) {
70
+ const pluginDir = resolvePluginDir(outDir);
71
+ if (!pluginDir) {
72
+ this.warn("[@fcannizzaro/streamdeck-react] Could not resolve .sdPlugin directory from output path. Manifest generation skipped.");
73
+ return;
74
+ }
75
+ const codePath = deriveCodePath(outputOptions.file ?? join(outDir, "plugin.mjs"), pluginDir);
76
+ const fullConfig = {
77
+ ...options.manifest,
78
+ actions: extractedActions.map(extractedToActionSource)
79
+ };
80
+ const errors = validateManifestConfig(fullConfig, (msg) => this.warn(msg));
81
+ if (errors.length > 0) this.warn(`[@fcannizzaro/streamdeck-react] Manifest validation found ${errors.length} issue(s)`);
82
+ const content = generateManifestJsonString(fullConfig, codePath);
83
+ const manifestPath = join(pluginDir, "manifest.json");
84
+ if (writeManifestIfChanged(manifestPath, content)) console.log(`[@fcannizzaro/streamdeck-react] Generated ${manifestPath}`);
85
+ }
59
86
  }
60
87
  };
61
88
  }
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ComponentType, ReactNode } from 'react';
2
2
  import { JsonObject, JsonValue } from '@elgato/utils';
3
3
  import { AdapterActionHandle, StreamDeckAdapter } from './adapter/types';
4
+ import { ActionManifestInfo, PluginManifestInfo } from './manifest-types';
4
5
  /** Controller surface type. */
5
6
  export type Controller = "Keypad" | "Encoder";
6
7
  /** Grid coordinates for a key or encoder on a device. */
@@ -81,6 +82,12 @@ export interface PluginConfig {
81
82
  fonts: FontConfig[];
82
83
  actions: ActionDefinition[];
83
84
  wrapper?: WrapperComponent;
85
+ /**
86
+ * Plugin manifest metadata. Optional — used for runtime
87
+ * documentation. For manifest generation, provide plugin-level
88
+ * info via the bundler plugin's `manifest` option.
89
+ */
90
+ info?: PluginManifestInfo;
84
91
  /**
85
92
  * Takumi renderer backend.
86
93
  *
@@ -111,28 +118,6 @@ export interface PluginConfig {
111
118
  export interface Plugin {
112
119
  connect(): Promise<void>;
113
120
  }
114
- export interface ManifestActions {
115
- }
116
- /** Action UUID — a union of manifest UUIDs when available, plain `string` otherwise. */
117
- export type ActionUUID = [keyof ManifestActions] extends [never] ? string : Extract<keyof ManifestActions, string>;
118
- type HasController<UUID extends string, C extends string> = UUID extends keyof ManifestActions ? ManifestActions[UUID] extends {
119
- controllers: readonly (infer Item)[];
120
- } ? C extends Item ? true : false : false : false;
121
- type KeySurface<UUID extends string> = HasController<UUID, "Keypad"> extends true ? {
122
- key: ComponentType;
123
- } : {
124
- key?: ComponentType;
125
- };
126
- type EncoderSurface<UUID extends string> = HasController<UUID, "Encoder"> extends true ? {
127
- dial: ComponentType;
128
- touchStrip?: ComponentType;
129
- } | {
130
- dial?: ComponentType;
131
- touchStrip: ComponentType;
132
- } : {
133
- dial?: ComponentType;
134
- touchStrip?: ComponentType;
135
- };
136
121
  export interface ActionConfig<S extends JsonObject = JsonObject> {
137
122
  uuid: string;
138
123
  key?: ComponentType;
@@ -143,19 +128,15 @@ export interface ActionConfig<S extends JsonObject = JsonObject> {
143
128
  dialLayout?: EncoderLayout;
144
129
  wrapper?: WrapperComponent;
145
130
  defaultSettings?: Partial<S>;
131
+ /**
132
+ * Action manifest metadata. This is the **primary source** for
133
+ * manifest.json generation — the bundler plugin auto-extracts
134
+ * `info` from each `defineAction()` call at build time.
135
+ *
136
+ * Set `disabled: true` to exclude this action from the manifest.
137
+ */
138
+ info?: ActionManifestInfo;
146
139
  }
147
- /** Resolved action config shape. When `ManifestActions` is populated (via `streamdeck-env.d.ts`), this becomes a mapped type that iterates over every UUID in the manifest and produces a discriminated union. Each member intersects `KeySurface<UUID>` and `EncoderSurface<UUID>` to enforce controller-specific requirements. When `ManifestActions` is empty, it falls back to the permissive `ActionConfig<S>`. */
148
- export type ActionConfigInput<S extends JsonObject = JsonObject> = [keyof ManifestActions] extends [
149
- never
150
- ] ? ActionConfig<S> : {
151
- [UUID in ActionUUID]: {
152
- uuid: UUID;
153
- /** Encoder feedback layout. Defaults to a full-width `pixmap` canvas layout. Custom layouts should include a `pixmap` item keyed as `canvas`. */
154
- dialLayout?: EncoderLayout;
155
- wrapper?: WrapperComponent;
156
- defaultSettings?: Partial<S>;
157
- } & KeySurface<UUID> & EncoderSurface<UUID>;
158
- }[ActionUUID];
159
140
  export interface ActionDefinition<S extends JsonObject = JsonObject> {
160
141
  uuid: string;
161
142
  key?: ComponentType;
@@ -166,6 +147,11 @@ export interface ActionDefinition<S extends JsonObject = JsonObject> {
166
147
  dialLayout?: EncoderLayout;
167
148
  wrapper?: WrapperComponent;
168
149
  defaultSettings: Partial<S>;
150
+ /**
151
+ * Action manifest metadata. Carried through from defineAction()
152
+ * for runtime access and manifest generation.
153
+ */
154
+ info?: ActionManifestInfo;
169
155
  }
170
156
  export interface DeviceInfo {
171
157
  id: string;
package/dist/vite.d.ts CHANGED
@@ -1,22 +1,37 @@
1
1
  import { Plugin } from 'vite';
2
2
  import { StreamDeckTargetOptions } from './bundler-shared';
3
+ import { PluginManifestInfo } from './manifest-types';
3
4
  export type { StreamDeckPlatform, StreamDeckArch, StreamDeckTarget, StreamDeckTargetOptions, TakumiBackend, } from './bundler-shared';
5
+ export type { ManifestActionSource, PluginManifestInfo, ActionManifestInfo, ManifestController, ManifestEncoderInfo, ManifestTriggerDescription, ManifestStateInfo, ManifestOSInfo, ManifestNodejsInfo, ManifestProfileInfo, } from './manifest-types';
4
6
  export interface StreamDeckReactOptions extends StreamDeckTargetOptions {
5
7
  /**
6
8
  * The plugin UUID used to restart the plugin after each build
7
9
  * (e.g. `"com.example.react-pokemon"`).
8
10
  *
9
11
  * When set, the plugin will run `streamdeck restart <uuid>` after
10
- * each successful build.
12
+ * each successful build. If `manifest` is set, the UUID is
13
+ * auto-derived from `manifest.uuid`.
11
14
  */
12
15
  uuid?: string;
13
16
  /**
14
- * Path to the plugin `manifest.json`. When omitted, the plugin
15
- * auto-detects by scanning the project root for a `*.sdPlugin/manifest.json`.
17
+ * Code-first manifest generation. When a `PluginManifestInfo` object
18
+ * is provided, the plugin generates `manifest.json` in the `.sdPlugin`
19
+ * directory during `writeBundle`.
16
20
  *
17
- * Set to `false` to disable manifest type generation entirely.
21
+ * Actions are **auto-extracted** from `defineAction()` calls in the
22
+ * source code — no need to list them here. The plugin scans the
23
+ * module graph during the build and extracts `uuid`, `info`, and
24
+ * component presence from each `defineAction()` call.
25
+ *
26
+ * Actions with `info.disabled: true` are skipped.
27
+ *
28
+ * Auto-derived defaults:
29
+ * - `CodePath` from the bundler output path
30
+ * - `Controllers` from key/dial/touchStrip presence
31
+ * - `OS`, `Nodejs`, `SDKVersion`, `Software` have defaults
32
+ * - `States` default to `[{ Image: icon }]`
18
33
  */
19
- manifest?: string | false;
34
+ manifest?: PluginManifestInfo;
20
35
  }
21
36
  /**
22
37
  * Vite plugin for Stream Deck React projects.
@@ -24,10 +39,11 @@ export interface StreamDeckReactOptions extends StreamDeckTargetOptions {
24
39
  * Responsibilities mapped to Vite lifecycle hooks:
25
40
  *
26
41
  * configResolved → detect dev/production mode, set strip flags
27
- * buildStart → generate streamdeck-env.d.ts from manifest.json
42
+ * buildStart → validate plugin UUID format (early check)
43
+ * moduleParsed → extract defineAction() metadata from each module
28
44
  * resolveId → redirect devtools imports (production) + font imports
29
45
  * load → return noop devtools stub + inline font as base64 Buffer
30
- * writeBundle → copy native .node bindings to output directory
46
+ * writeBundle → copy native .node bindings + generate manifest.json
31
47
  * closeBundle → restart Stream Deck plugin (optional, via CLI)
32
48
  *
33
49
  * Font inlining: