@fcannizzaro/streamdeck-react 0.1.12 → 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.
- package/README.md +11 -8
- package/dist/action.d.ts +2 -2
- package/dist/action.js +2 -1
- package/dist/bundler-shared.d.ts +31 -0
- package/dist/bundler-shared.js +64 -2
- package/dist/font-inline.js +1 -1
- package/dist/google-font.d.ts +61 -0
- package/dist/google-font.js +124 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -1
- package/dist/manifest-extract.d.ts +32 -0
- package/dist/manifest-extract.js +141 -0
- package/dist/manifest-gen.d.ts +52 -0
- package/dist/manifest-gen.js +229 -0
- package/dist/manifest-types.d.ts +238 -0
- package/dist/plugin.js +44 -35
- package/dist/render/render-pool.js +1 -1
- package/dist/rollup.d.ts +37 -10
- package/dist/rollup.js +43 -14
- package/dist/roots/registry.js +20 -20
- package/dist/types.d.ts +35 -35
- package/dist/vite.d.ts +24 -8
- package/dist/vite.js +48 -13
- package/package.json +10 -5
- package/dist/manifest-codegen.d.ts +0 -38
- package/dist/manifest-codegen.js +0 -110
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
//#region src/manifest-gen.ts
|
|
4
|
+
/**
|
|
5
|
+
* Validate just the plugin UUID format.
|
|
6
|
+
*
|
|
7
|
+
* Used in `buildStart` for early error reporting before action
|
|
8
|
+
* extraction is complete.
|
|
9
|
+
*
|
|
10
|
+
* @returns A validation error if the UUID is invalid, or `null` if valid.
|
|
11
|
+
*/
|
|
12
|
+
function validatePluginUUID(uuid) {
|
|
13
|
+
if (!/^([a-z0-9-]+)(\.[a-z0-9-]+)+$/.test(uuid)) return {
|
|
14
|
+
field: "uuid",
|
|
15
|
+
message: `Plugin UUID "${uuid}" must be in reverse-DNS format (lowercase alphanumeric, hyphens, periods)`
|
|
16
|
+
};
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validate a full ManifestConfig for correctness.
|
|
21
|
+
*
|
|
22
|
+
* Checks:
|
|
23
|
+
* - All action UUIDs are prefixed with the plugin UUID
|
|
24
|
+
* - No duplicate action UUIDs
|
|
25
|
+
* - Plugin UUID matches reverse-DNS pattern
|
|
26
|
+
*
|
|
27
|
+
* Called in `writeBundle` after action extraction is complete.
|
|
28
|
+
*/
|
|
29
|
+
function validateManifestConfig(config, warn) {
|
|
30
|
+
const errors = [];
|
|
31
|
+
const uuidError = validatePluginUUID(config.uuid);
|
|
32
|
+
if (uuidError) errors.push(uuidError);
|
|
33
|
+
const prefix = config.uuid + ".";
|
|
34
|
+
const seenUuids = /* @__PURE__ */ new Set();
|
|
35
|
+
for (const action of config.actions) {
|
|
36
|
+
if (!action.uuid.startsWith(prefix)) {
|
|
37
|
+
const error = {
|
|
38
|
+
field: `actions[${action.uuid}].uuid`,
|
|
39
|
+
message: `Action UUID "${action.uuid}" must be prefixed with plugin UUID "${config.uuid}."`
|
|
40
|
+
};
|
|
41
|
+
errors.push(error);
|
|
42
|
+
warn?.(`[@fcannizzaro/streamdeck-react] ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
if (seenUuids.has(action.uuid)) errors.push({
|
|
45
|
+
field: `actions[${action.uuid}].uuid`,
|
|
46
|
+
message: `Duplicate action UUID "${action.uuid}"`
|
|
47
|
+
});
|
|
48
|
+
seenUuids.add(action.uuid);
|
|
49
|
+
}
|
|
50
|
+
return errors;
|
|
51
|
+
}
|
|
52
|
+
/** Add a key to the record only if the value is defined. */
|
|
53
|
+
function addIf(record, key, value) {
|
|
54
|
+
if (value !== void 0 && value !== null) record[key] = value;
|
|
55
|
+
}
|
|
56
|
+
function buildTriggerDescription(td) {
|
|
57
|
+
const out = {};
|
|
58
|
+
addIf(out, "Rotate", td.rotate);
|
|
59
|
+
addIf(out, "Push", td.push);
|
|
60
|
+
addIf(out, "Touch", td.touch);
|
|
61
|
+
addIf(out, "LongTouch", td.longTouch);
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
function buildEncoder(encoder) {
|
|
65
|
+
const out = {};
|
|
66
|
+
addIf(out, "layout", encoder.layout);
|
|
67
|
+
addIf(out, "Icon", encoder.icon);
|
|
68
|
+
addIf(out, "StackColor", encoder.stackColor);
|
|
69
|
+
addIf(out, "background", encoder.background);
|
|
70
|
+
if (encoder.triggerDescription) out["TriggerDescription"] = buildTriggerDescription(encoder.triggerDescription);
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
function buildState(state) {
|
|
74
|
+
const out = { Image: state.image };
|
|
75
|
+
addIf(out, "Name", state.name);
|
|
76
|
+
addIf(out, "Title", state.title);
|
|
77
|
+
addIf(out, "ShowTitle", state.showTitle);
|
|
78
|
+
addIf(out, "TitleAlignment", state.titleAlignment);
|
|
79
|
+
addIf(out, "TitleColor", state.titleColor);
|
|
80
|
+
addIf(out, "FontFamily", state.fontFamily);
|
|
81
|
+
addIf(out, "FontSize", state.fontSize);
|
|
82
|
+
addIf(out, "FontStyle", state.fontStyle);
|
|
83
|
+
addIf(out, "FontUnderline", state.fontUnderline);
|
|
84
|
+
addIf(out, "MultiActionImage", state.multiActionImage);
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Derive Controllers from an action definition.
|
|
89
|
+
*
|
|
90
|
+
* Priority:
|
|
91
|
+
* 1. Explicit `controllers` on info → use as-is
|
|
92
|
+
* 2. Derived from key/dial/touchStrip presence:
|
|
93
|
+
* - key → includes "Keypad"
|
|
94
|
+
* - dial or touchStrip → includes "Encoder"
|
|
95
|
+
* - both → ["Keypad", "Encoder"]
|
|
96
|
+
* 3. Default → ["Keypad"]
|
|
97
|
+
*/
|
|
98
|
+
function deriveControllers(action) {
|
|
99
|
+
const info = action.info;
|
|
100
|
+
if (info?.controllers) return info.controllers.filter((c) => c != null);
|
|
101
|
+
const hasKey = action.key != null;
|
|
102
|
+
const hasEncoder = action.dial != null || action.touchStrip != null;
|
|
103
|
+
if (hasKey && hasEncoder) return ["Keypad", "Encoder"];
|
|
104
|
+
if (hasEncoder) return ["Encoder"];
|
|
105
|
+
if (hasKey) return ["Keypad"];
|
|
106
|
+
if (info?.encoder) return ["Encoder"];
|
|
107
|
+
return ["Keypad"];
|
|
108
|
+
}
|
|
109
|
+
function buildAction(action) {
|
|
110
|
+
const info = action.info;
|
|
111
|
+
if (!info) throw new Error(`[@fcannizzaro/streamdeck-react] Action "${action.uuid}" is missing \`info\`. Add info: { name, icon } to the defineAction() call.`);
|
|
112
|
+
const controllers = deriveControllers(action);
|
|
113
|
+
const states = info.states ? info.states.map(buildState) : [{ Image: info.icon }];
|
|
114
|
+
const out = {
|
|
115
|
+
UUID: action.uuid,
|
|
116
|
+
Name: info.name,
|
|
117
|
+
Icon: info.icon,
|
|
118
|
+
Controllers: controllers,
|
|
119
|
+
States: states
|
|
120
|
+
};
|
|
121
|
+
addIf(out, "Tooltip", info.tooltip);
|
|
122
|
+
addIf(out, "DisableAutomaticStates", info.disableAutomaticStates);
|
|
123
|
+
addIf(out, "DisableCaching", info.disableCaching);
|
|
124
|
+
addIf(out, "SupportedInMultiActions", info.supportedInMultiActions);
|
|
125
|
+
addIf(out, "SupportedInKeyLogicActions", info.supportedInKeyLogicActions);
|
|
126
|
+
addIf(out, "VisibleInActionsList", info.visibleInActionsList);
|
|
127
|
+
addIf(out, "UserTitleEnabled", info.userTitleEnabled);
|
|
128
|
+
addIf(out, "PropertyInspectorPath", info.propertyInspectorPath);
|
|
129
|
+
addIf(out, "SupportURL", info.supportUrl);
|
|
130
|
+
if (info.encoder) out["Encoder"] = buildEncoder(info.encoder);
|
|
131
|
+
if (info.os) out["OS"] = info.os;
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
var DEFAULT_OS = [{
|
|
135
|
+
platform: "mac",
|
|
136
|
+
minimumVersion: "13"
|
|
137
|
+
}, {
|
|
138
|
+
platform: "windows",
|
|
139
|
+
minimumVersion: "10"
|
|
140
|
+
}];
|
|
141
|
+
function buildOS(osEntries) {
|
|
142
|
+
return osEntries.filter((o) => o != null).map((o) => ({
|
|
143
|
+
Platform: o.platform,
|
|
144
|
+
MinimumVersion: o.minimumVersion
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
function buildNodejs(nodejs) {
|
|
148
|
+
const out = { Version: nodejs.version };
|
|
149
|
+
addIf(out, "Debug", nodejs.debug);
|
|
150
|
+
addIf(out, "GenerateProfilerOutput", nodejs.generateProfilerOutput);
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
function buildProfile(profile) {
|
|
154
|
+
const out = {
|
|
155
|
+
Name: profile.name,
|
|
156
|
+
DeviceType: profile.deviceType
|
|
157
|
+
};
|
|
158
|
+
addIf(out, "AutoInstall", profile.autoInstall);
|
|
159
|
+
addIf(out, "DontAutoSwitchWhenInstalled", profile.dontAutoSwitchWhenInstalled);
|
|
160
|
+
addIf(out, "Readonly", profile.readonly);
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Build the full manifest JSON object from a ManifestConfig.
|
|
165
|
+
*
|
|
166
|
+
* Applies all auto-derivation defaults and transforms camelCase
|
|
167
|
+
* to the PascalCase format expected by the Elgato schema.
|
|
168
|
+
*
|
|
169
|
+
* @param config - The manifest configuration
|
|
170
|
+
* @param codePath - Override CodePath (typically derived from bundler output)
|
|
171
|
+
*/
|
|
172
|
+
function buildManifestJson(config, codePath) {
|
|
173
|
+
const osEntries = config.os ? config.os.filter((o) => o != null) : DEFAULT_OS;
|
|
174
|
+
const nodejs = config.nodejs ?? { version: "24" };
|
|
175
|
+
const out = {
|
|
176
|
+
$schema: "https://schemas.elgato.com/streamdeck/plugins/manifest.json",
|
|
177
|
+
UUID: config.uuid,
|
|
178
|
+
Name: config.name,
|
|
179
|
+
Author: config.author,
|
|
180
|
+
Description: config.description,
|
|
181
|
+
Icon: config.icon,
|
|
182
|
+
Version: config.version,
|
|
183
|
+
CodePath: codePath ?? config.codePath ?? "bin/plugin.mjs",
|
|
184
|
+
OS: buildOS(osEntries),
|
|
185
|
+
Nodejs: buildNodejs(nodejs),
|
|
186
|
+
SDKVersion: config.sdkVersion ?? 2,
|
|
187
|
+
Software: { MinimumVersion: config.software?.minimumVersion ?? "7.1" },
|
|
188
|
+
Category: config.category ?? config.name,
|
|
189
|
+
CategoryIcon: config.categoryIcon ?? config.icon,
|
|
190
|
+
Actions: config.actions.map(buildAction)
|
|
191
|
+
};
|
|
192
|
+
addIf(out, "URL", config.url);
|
|
193
|
+
addIf(out, "SupportURL", config.supportUrl);
|
|
194
|
+
addIf(out, "PropertyInspectorPath", config.propertyInspectorPath);
|
|
195
|
+
addIf(out, "DefaultWindowSize", config.defaultWindowSize);
|
|
196
|
+
addIf(out, "CodePathMac", config.codePathMac);
|
|
197
|
+
addIf(out, "CodePathWin", config.codePathWin);
|
|
198
|
+
if (config.applicationsToMonitor) out["ApplicationsToMonitor"] = config.applicationsToMonitor;
|
|
199
|
+
if (config.profiles?.length) out["Profiles"] = config.profiles.map(buildProfile);
|
|
200
|
+
return out;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Generate the full manifest JSON string from a ManifestConfig.
|
|
204
|
+
*
|
|
205
|
+
* @param config - The manifest configuration
|
|
206
|
+
* @param codePath - Override CodePath (typically derived from bundler output)
|
|
207
|
+
* @returns Formatted JSON string
|
|
208
|
+
*/
|
|
209
|
+
function generateManifestJsonString(config, codePath) {
|
|
210
|
+
const json = buildManifestJson(config, codePath);
|
|
211
|
+
return JSON.stringify(json, null, 2) + "\n";
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Write manifest.json only when the content has changed.
|
|
215
|
+
* Creates the parent directory if it does not exist.
|
|
216
|
+
*
|
|
217
|
+
* @returns `true` if the file was written, `false` if content was unchanged.
|
|
218
|
+
*/
|
|
219
|
+
function writeManifestIfChanged(outPath, content) {
|
|
220
|
+
if (existsSync(outPath)) {
|
|
221
|
+
if (readFileSync(outPath, "utf-8") === content) return false;
|
|
222
|
+
}
|
|
223
|
+
const dir = dirname(outPath);
|
|
224
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
225
|
+
writeFileSync(outPath, content);
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
//#endregion
|
|
229
|
+
export { generateManifestJsonString, validateManifestConfig, validatePluginUUID, writeManifestIfChanged };
|
|
@@ -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
|
+
}
|
package/dist/plugin.js
CHANGED
|
@@ -7,46 +7,55 @@ import { Renderer } from "@takumi-rs/core";
|
|
|
7
7
|
//#region src/plugin.ts
|
|
8
8
|
function createPlugin(config) {
|
|
9
9
|
const adapter = config.adapter ?? physicalDevice();
|
|
10
|
-
const renderer = new Renderer({ fonts: config.fonts.map((f) => ({
|
|
11
|
-
name: f.name,
|
|
12
|
-
data: f.data,
|
|
13
|
-
weight: f.weight,
|
|
14
|
-
style: f.style
|
|
15
|
-
})) });
|
|
16
|
-
const renderPool = config.useWorker !== false ? new RenderPool(config.fonts) : null;
|
|
17
|
-
const renderConfig = {
|
|
18
|
-
renderer,
|
|
19
|
-
imageFormat: config.imageFormat ?? "png",
|
|
20
|
-
caching: config.caching ?? true,
|
|
21
|
-
devicePixelRatio: config.devicePixelRatio ?? 1,
|
|
22
|
-
debug: config.debug ?? process.env.NODE_ENV !== "production",
|
|
23
|
-
imageCacheMaxBytes: config.imageCacheMaxBytes ?? 16 * 1024 * 1024,
|
|
24
|
-
touchStripCacheMaxBytes: config.touchStripCacheMaxBytes ?? 8 * 1024 * 1024,
|
|
25
|
-
renderPool
|
|
26
|
-
};
|
|
27
|
-
const registry = new RootRegistry(renderConfig, adapter, async (settings) => {
|
|
28
|
-
await adapter.setGlobalSettings(settings);
|
|
29
|
-
}, config.wrapper);
|
|
30
|
-
adapter.getGlobalSettings().then((gs) => {
|
|
31
|
-
registry.setGlobalSettings(gs);
|
|
32
|
-
}).catch((err) => {
|
|
33
|
-
console.error("[@fcannizzaro/streamdeck-react] Failed to load global settings:", err);
|
|
34
|
-
});
|
|
35
|
-
adapter.onGlobalSettingsChanged((settings) => {
|
|
36
|
-
registry.setGlobalSettings(settings);
|
|
37
|
-
});
|
|
38
|
-
for (const definition of config.actions) registerActionWithAdapter(adapter, definition, registry, config.onActionError);
|
|
39
|
-
if (renderConfig.debug) metrics.enable();
|
|
40
|
-
if (config.devtools) startDevtoolsServer({
|
|
41
|
-
devtoolsName: adapter.pluginUUID,
|
|
42
|
-
registry,
|
|
43
|
-
renderConfig
|
|
44
|
-
});
|
|
45
10
|
return { async connect() {
|
|
11
|
+
const takumiMode = config.takumi ?? "native-binding";
|
|
12
|
+
const renderPool = (takumiMode === "wasm" ? false : config.useWorker !== false) ? new RenderPool(config.fonts) : null;
|
|
13
|
+
const renderConfig = {
|
|
14
|
+
renderer: await initializeRenderer(takumiMode, config.fonts),
|
|
15
|
+
imageFormat: config.imageFormat ?? "png",
|
|
16
|
+
caching: config.caching ?? true,
|
|
17
|
+
devicePixelRatio: config.devicePixelRatio ?? 1,
|
|
18
|
+
debug: config.debug ?? process.env.NODE_ENV !== "production",
|
|
19
|
+
imageCacheMaxBytes: config.imageCacheMaxBytes ?? 16 * 1024 * 1024,
|
|
20
|
+
touchStripCacheMaxBytes: config.touchStripCacheMaxBytes ?? 8 * 1024 * 1024,
|
|
21
|
+
renderPool
|
|
22
|
+
};
|
|
23
|
+
const registry = new RootRegistry(renderConfig, adapter, async (settings) => {
|
|
24
|
+
await adapter.setGlobalSettings(settings);
|
|
25
|
+
}, config.wrapper);
|
|
26
|
+
adapter.getGlobalSettings().then((gs) => {
|
|
27
|
+
registry.setGlobalSettings(gs);
|
|
28
|
+
}).catch((err) => {
|
|
29
|
+
console.error("[@fcannizzaro/streamdeck-react] Failed to load global settings:", err);
|
|
30
|
+
});
|
|
31
|
+
adapter.onGlobalSettingsChanged((settings) => {
|
|
32
|
+
registry.setGlobalSettings(settings);
|
|
33
|
+
});
|
|
34
|
+
for (const definition of config.actions) registerActionWithAdapter(adapter, definition, registry, config.onActionError);
|
|
35
|
+
if (renderConfig.debug) metrics.enable();
|
|
36
|
+
if (config.devtools) startDevtoolsServer({
|
|
37
|
+
devtoolsName: adapter.pluginUUID,
|
|
38
|
+
registry,
|
|
39
|
+
renderConfig
|
|
40
|
+
});
|
|
46
41
|
if (renderPool != null) renderPool.initialize().catch(() => {});
|
|
47
42
|
await adapter.connect();
|
|
48
43
|
} };
|
|
49
44
|
}
|
|
45
|
+
async function initializeRenderer(mode, fonts) {
|
|
46
|
+
const fontData = fonts.map((f) => ({
|
|
47
|
+
name: f.name,
|
|
48
|
+
data: f.data,
|
|
49
|
+
weight: f.weight,
|
|
50
|
+
style: f.style
|
|
51
|
+
}));
|
|
52
|
+
if (mode === "wasm") {
|
|
53
|
+
const wasm = await import("@takumi-rs/wasm");
|
|
54
|
+
await wasm.default();
|
|
55
|
+
return new wasm.Renderer({ fonts: fontData });
|
|
56
|
+
}
|
|
57
|
+
return new Renderer({ fonts: fontData });
|
|
58
|
+
}
|
|
50
59
|
function registerActionWithAdapter(adapter, definition, registry, onError) {
|
|
51
60
|
const handleError = (actionId, err) => {
|
|
52
61
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -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,
|