@lukaskj/xmonkey 2.2.4 → 2.2.6
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 +1 -1
- package/dist/build.d.ts +1 -0
- package/dist/build.js +205 -0
- package/dist/console-script/console-script.decorator.d.ts +3 -0
- package/dist/console-script/console-script.decorator.js +9 -0
- package/dist/console-script/console-script.interface.d.ts +6 -0
- package/dist/console-script/console-script.interface.js +3 -0
- package/dist/console-script/index.d.ts +2 -0
- package/dist/console-script/index.js +2 -0
- package/dist/esbuild/build.d.ts +1 -0
- package/dist/esbuild/build.js +28 -0
- package/dist/esbuild/plugins/xmonkey-output-stats-plugin.d.ts +2 -0
- package/dist/esbuild/plugins/xmonkey-output-stats-plugin.js +17 -0
- package/dist/esbuild/plugins/xmonkey-strip-metadata-plugin.d.ts +2 -0
- package/dist/esbuild/plugins/xmonkey-strip-metadata-plugin.js +76 -0
- package/dist/esbuild/plugins/xmonkey-styles-plugin.d.ts +2 -0
- package/dist/esbuild/plugins/xmonkey-styles-plugin.js +34 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +29 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -0
- package/dist/styles/_base.scss +3 -0
- package/dist/styles/_colors.scss +13 -0
- package/dist/styles/_utils.scss +82 -0
- package/dist/styles/_variables.scss +10 -0
- package/dist/styles/_xmonkey-wrapper.scss +89 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.js +1 -0
- package/dist/ui-script/index.d.ts +2 -0
- package/dist/ui-script/index.js +2 -0
- package/dist/ui-script/ui-script.decorator.d.ts +3 -0
- package/dist/ui-script/ui-script.decorator.js +19 -0
- package/dist/ui-script/ui-script.interface.d.ts +5 -0
- package/dist/ui-script/ui-script.interface.js +1 -0
- package/dist/utils/get-storage-key-id-from-string.d.ts +1 -0
- package/dist/utils/get-storage-key-id-from-string.js +3 -0
- package/dist/utils/is-null-or-undefined.d.ts +2 -0
- package/dist/utils/is-null-or-undefined.js +4 -0
- package/dist/utils/sleep.d.ts +1 -0
- package/dist/utils/sleep.js +3 -0
- package/dist/x-monkey-window-component.d.ts +7 -0
- package/dist/x-monkey-window-component.js +16 -0
- package/package.json +30 -28
package/README.md
CHANGED
|
@@ -112,4 +112,4 @@ xmonkey src/example-console-script.tsx
|
|
|
112
112
|
|
|
113
113
|
### Known bugs
|
|
114
114
|
|
|
115
|
-
- The UiScript render function has a
|
|
115
|
+
- The UiScript render function has a bug that it cannot have any hook or it won't work. The workaround is to return a single component in the UiScript that this component can use any preact hook as usual. See example [here](./examples/src/whatsapp-theme/whatsapp-theme.tsx).
|
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __copyProps = (to, from, except, desc) => {
|
|
8
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
9
|
+
for (let key of __getOwnPropNames(from))
|
|
10
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
11
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
12
|
+
}
|
|
13
|
+
return to;
|
|
14
|
+
};
|
|
15
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
16
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
17
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
18
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
19
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
20
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
21
|
+
mod
|
|
22
|
+
));
|
|
23
|
+
|
|
24
|
+
// src/esbuild/build.ts
|
|
25
|
+
var esbuild = __toESM(require("esbuild"));
|
|
26
|
+
var import_esbuild_sass_plugin = require("esbuild-sass-plugin");
|
|
27
|
+
|
|
28
|
+
// src/esbuild/plugins/xmonkey-strip-metadata-plugin.ts
|
|
29
|
+
var import_promises = require("fs/promises");
|
|
30
|
+
var import_json5 = __toESM(require("json5"));
|
|
31
|
+
function xMonkeyStripMetadataPlugin() {
|
|
32
|
+
return {
|
|
33
|
+
name: "xmonkey-strip-metadata-plugin",
|
|
34
|
+
setup(build2) {
|
|
35
|
+
let foundMetadata = false;
|
|
36
|
+
let metadataContent = "";
|
|
37
|
+
build2.onLoad({ filter: /.(ts|tsx)/, namespace: "file" }, async (args) => {
|
|
38
|
+
if (foundMetadata)
|
|
39
|
+
return;
|
|
40
|
+
const source = await (0, import_promises.readFile)(args.path, "utf8");
|
|
41
|
+
const scriptMetadataIndex = source.match(/@(ConsoleScript|UiScript)\(/)?.index;
|
|
42
|
+
if (!scriptMetadataIndex || scriptMetadataIndex < 0)
|
|
43
|
+
return;
|
|
44
|
+
foundMetadata = true;
|
|
45
|
+
const regex = /\@(ConsoleScript|UiScript)\([^\)]*\)(\.[^\)]*\))?/gi;
|
|
46
|
+
const metadataDecoratorMatcher = source.match(regex);
|
|
47
|
+
if (metadataDecoratorMatcher) {
|
|
48
|
+
metadataContent = metadataDecoratorMatcher.at(0);
|
|
49
|
+
const startJsonMetadataIndex = metadataContent.indexOf("{");
|
|
50
|
+
const endJsonMetadataIndex = metadataContent.lastIndexOf("}");
|
|
51
|
+
const metadataJsonString = metadataContent.substring(startJsonMetadataIndex, endJsonMetadataIndex + 1);
|
|
52
|
+
const contents = source.replace(metadataJsonString, "");
|
|
53
|
+
const extension = args.path.split(".").pop();
|
|
54
|
+
const loader = extension === "tsx" ? "tsx" : "ts";
|
|
55
|
+
return { contents, loader };
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
});
|
|
59
|
+
build2.onEnd(async (result) => {
|
|
60
|
+
if (!build2.initialOptions?.outfile || !build2.initialOptions?.bundle) {
|
|
61
|
+
console.error("Wrong build configuration. Options 'bundle' must be enabled and 'outfile' must be set.");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!foundMetadata) {
|
|
65
|
+
console.error("ScriptMetadata decorator not found.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (result.errors.length) {
|
|
69
|
+
console.error("Error building. Script Metadata cannot be added to final script.");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const fileContents = await (0, import_promises.readFile)(build2.initialOptions.outfile);
|
|
73
|
+
const scriptMetadataString = getScriptMetadataString(metadataContent);
|
|
74
|
+
await (0, import_promises.writeFile)(build2.initialOptions.outfile, `${scriptMetadataString}
|
|
75
|
+
|
|
76
|
+
${fileContents.toString()}`);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function getScriptMetadataString(scriptMetadataFunctionCallString) {
|
|
82
|
+
scriptMetadataFunctionCallString = scriptMetadataFunctionCallString.trim();
|
|
83
|
+
const startJsonMetadataIndex = scriptMetadataFunctionCallString.indexOf("{");
|
|
84
|
+
const endJsonMetadataIndex = scriptMetadataFunctionCallString.lastIndexOf("}");
|
|
85
|
+
if (startJsonMetadataIndex < 0 || endJsonMetadataIndex < 0) {
|
|
86
|
+
return "";
|
|
87
|
+
}
|
|
88
|
+
const jsonMetadataString = scriptMetadataFunctionCallString.substring(
|
|
89
|
+
startJsonMetadataIndex,
|
|
90
|
+
endJsonMetadataIndex + 1
|
|
91
|
+
);
|
|
92
|
+
const metadataObject = import_json5.default.parse(jsonMetadataString);
|
|
93
|
+
const tag = "// ==UserScript==";
|
|
94
|
+
const tagEnd = "// ==/UserScript==";
|
|
95
|
+
const headersArr = [];
|
|
96
|
+
const spaces = 13;
|
|
97
|
+
for (const key in metadataObject) {
|
|
98
|
+
if (Array.isArray(metadataObject[key])) {
|
|
99
|
+
metadataObject[key].forEach((item) => {
|
|
100
|
+
headersArr.push(`${key.padEnd(spaces, " ")}${item}`);
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
headersArr.push(`${key.padEnd(spaces, " ")}${metadataObject[key]}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const headers = headersArr.map((h) => `// ${h}`).join("\n");
|
|
107
|
+
return `${tag}
|
|
108
|
+
${headers}
|
|
109
|
+
${tagEnd}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/esbuild/plugins/xmonkey-styles-plugin.ts
|
|
113
|
+
var import_promises2 = require("fs/promises");
|
|
114
|
+
function xMonkeyStylesPlugin() {
|
|
115
|
+
return {
|
|
116
|
+
name: "xmonkey-styles-plugin",
|
|
117
|
+
setup(build2) {
|
|
118
|
+
build2.onEnd(async (result) => {
|
|
119
|
+
if (!build2.initialOptions?.outfile || !build2.initialOptions?.bundle) {
|
|
120
|
+
console.error("Wrong build configuration. Options 'bundle' must be enabled and 'outfile' must be set.");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!result.metafile) {
|
|
124
|
+
console.warn("ESBuild metafile not enabled. Style bundle skipped.");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const outputs = result.metafile.outputs;
|
|
128
|
+
let cssFilePath = "";
|
|
129
|
+
for (const file in outputs) {
|
|
130
|
+
const ext = file.split(".").pop();
|
|
131
|
+
if (ext === "css") {
|
|
132
|
+
cssFilePath = file;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!cssFilePath.length) {
|
|
137
|
+
console.warn("[-] StyleSheet output skipped.");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const jsOutFile = build2.initialOptions.outfile;
|
|
141
|
+
const cssContents = (await (0, import_promises2.readFile)(cssFilePath)).toString();
|
|
142
|
+
(0, import_promises2.appendFile)(jsOutFile, `
|
|
143
|
+
GM.addStyle("\\
|
|
144
|
+
${cssContents.trim()}\\
|
|
145
|
+
");`);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/esbuild/plugins/xmonkey-output-stats-plugin.ts
|
|
152
|
+
function xMonkeyOutputStatsPlugin() {
|
|
153
|
+
return {
|
|
154
|
+
name: "xmonkey-output-stats-plugin",
|
|
155
|
+
setup(build2) {
|
|
156
|
+
build2.onEnd(async (result) => {
|
|
157
|
+
const outputs = result.metafile?.outputs;
|
|
158
|
+
const outputTotal = Object.keys(outputs).reduce((prev, cur) => prev + outputs[cur].bytes, 0);
|
|
159
|
+
const bundleTotal = humanFileSize(outputTotal);
|
|
160
|
+
console.log("[*] Bundle total:", bundleTotal);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function humanFileSize(size) {
|
|
166
|
+
const i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
|
|
167
|
+
return (size / Math.pow(1024, i)).toFixed(1) + "" + ["b", "kB", "MB", "GB", "TB"][i];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/esbuild/build.ts
|
|
171
|
+
async function buildXmonkeyScript(scriptBasePath) {
|
|
172
|
+
const entryFile2 = scriptBasePath;
|
|
173
|
+
console.info(`Building file: '${entryFile2}'`);
|
|
174
|
+
await esbuild.build({
|
|
175
|
+
entryPoints: [entryFile2],
|
|
176
|
+
outfile: "dist/index.js",
|
|
177
|
+
bundle: true,
|
|
178
|
+
treeShaking: true,
|
|
179
|
+
minify: process.env.DEBUG ? false : true,
|
|
180
|
+
platform: "browser",
|
|
181
|
+
format: "iife",
|
|
182
|
+
// target: "esnext",
|
|
183
|
+
sourcemap: false,
|
|
184
|
+
keepNames: true,
|
|
185
|
+
logLevel: "info",
|
|
186
|
+
metafile: true,
|
|
187
|
+
plugins: [
|
|
188
|
+
xMonkeyStripMetadataPlugin(),
|
|
189
|
+
// xMonkeyDevPlugin(),
|
|
190
|
+
(0, import_esbuild_sass_plugin.sassPlugin)({ style: "compressed" }),
|
|
191
|
+
xMonkeyStylesPlugin(),
|
|
192
|
+
xMonkeyOutputStatsPlugin()
|
|
193
|
+
]
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/build.ts
|
|
198
|
+
var entryFile = process.argv[2];
|
|
199
|
+
if (!entryFile) {
|
|
200
|
+
console.error(`No entryfile specified. Try adding the script to build in the argument.`);
|
|
201
|
+
console.error(`Example: npm run build src/example-script.ts`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
buildXmonkeyScript(entryFile);
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2VzYnVpbGQvYnVpbGQudHMiLCAiLi4vc3JjL2VzYnVpbGQvcGx1Z2lucy94bW9ua2V5LXN0cmlwLW1ldGFkYXRhLXBsdWdpbi50cyIsICIuLi9zcmMvZXNidWlsZC9wbHVnaW5zL3htb25rZXktc3R5bGVzLXBsdWdpbi50cyIsICIuLi9zcmMvZXNidWlsZC9wbHVnaW5zL3htb25rZXktb3V0cHV0LXN0YXRzLXBsdWdpbi50cyIsICIuLi9zcmMvYnVpbGQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAqIGFzIGVzYnVpbGQgZnJvbSBcImVzYnVpbGRcIjtcbmltcG9ydCB7IHNhc3NQbHVnaW4gfSBmcm9tIFwiZXNidWlsZC1zYXNzLXBsdWdpblwiO1xuaW1wb3J0IHsgeE1vbmtleVN0cmlwTWV0YWRhdGFQbHVnaW4gfSBmcm9tIFwiLi9wbHVnaW5zL3htb25rZXktc3RyaXAtbWV0YWRhdGEtcGx1Z2luLmpzXCI7XG5pbXBvcnQgeyB4TW9ua2V5U3R5bGVzUGx1Z2luIH0gZnJvbSBcIi4vcGx1Z2lucy94bW9ua2V5LXN0eWxlcy1wbHVnaW4uanNcIjtcbmltcG9ydCB7IHhNb25rZXlPdXRwdXRTdGF0c1BsdWdpbiB9IGZyb20gXCIuL3BsdWdpbnMveG1vbmtleS1vdXRwdXQtc3RhdHMtcGx1Z2luLmpzXCI7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZFhtb25rZXlTY3JpcHQoc2NyaXB0QmFzZVBhdGg6IHN0cmluZykge1xuICAvLyBsZXQgZW50cnlGaWxlID0gcHJvY2Vzcy5hcmd2WzJdO1xuICBjb25zdCBlbnRyeUZpbGUgPSBzY3JpcHRCYXNlUGF0aDtcbiAgY29uc29sZS5pbmZvKGBCdWlsZGluZyBmaWxlOiAnJHtlbnRyeUZpbGV9J2ApO1xuXG4gIGF3YWl0IGVzYnVpbGQuYnVpbGQoe1xuICAgIGVudHJ5UG9pbnRzOiBbZW50cnlGaWxlXSxcbiAgICBvdXRmaWxlOiBcImRpc3QvaW5kZXguanNcIixcbiAgICBidW5kbGU6IHRydWUsXG4gICAgdHJlZVNoYWtpbmc6IHRydWUsXG4gICAgbWluaWZ5OiBwcm9jZXNzLmVudi5ERUJVRyA/IGZhbHNlIDogdHJ1ZSxcbiAgICBwbGF0Zm9ybTogXCJicm93c2VyXCIsXG4gICAgZm9ybWF0OiBcImlpZmVcIixcbiAgICAvLyB0YXJnZXQ6IFwiZXNuZXh0XCIsXG4gICAgc291cmNlbWFwOiBmYWxzZSxcbiAgICBrZWVwTmFtZXM6IHRydWUsXG4gICAgbG9nTGV2ZWw6IFwiaW5mb1wiLFxuICAgIG1ldGFmaWxlOiB0cnVlLFxuICAgIHBsdWdpbnM6IFtcbiAgICAgIHhNb25rZXlTdHJpcE1ldGFkYXRhUGx1Z2luKCksXG4gICAgICAvLyB4TW9ua2V5RGV2UGx1Z2luKCksXG4gICAgICBzYXNzUGx1Z2luKHsgc3R5bGU6IFwiY29tcHJlc3NlZFwiIH0pLFxuICAgICAgeE1vbmtleVN0eWxlc1BsdWdpbigpLFxuICAgICAgeE1vbmtleU91dHB1dFN0YXRzUGx1Z2luKCksXG4gICAgXSxcbiAgfSk7XG59XG4iLCAiaW1wb3J0IHsgUGx1Z2luIH0gZnJvbSBcImVzYnVpbGRcIjtcbmltcG9ydCB7IHJlYWRGaWxlLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBKU09ONSBmcm9tIFwianNvbjVcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHhNb25rZXlTdHJpcE1ldGFkYXRhUGx1Z2luKCk6IFBsdWdpbiB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogXCJ4bW9ua2V5LXN0cmlwLW1ldGFkYXRhLXBsdWdpblwiLFxuICAgIHNldHVwKGJ1aWxkKSB7XG4gICAgICBsZXQgZm91bmRNZXRhZGF0YSA9IGZhbHNlO1xuICAgICAgbGV0IG1ldGFkYXRhQ29udGVudCA9IFwiXCI7XG5cbiAgICAgIGJ1aWxkLm9uTG9hZCh7IGZpbHRlcjogLy4odHN8dHN4KS8sIG5hbWVzcGFjZTogXCJmaWxlXCIgfSwgYXN5bmMgKGFyZ3MpID0+IHtcbiAgICAgICAgaWYgKGZvdW5kTWV0YWRhdGEpIHJldHVybjtcbiAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgcmVhZEZpbGUoYXJncy5wYXRoLCBcInV0ZjhcIik7XG4gICAgICAgIGNvbnN0IHNjcmlwdE1ldGFkYXRhSW5kZXggPSBzb3VyY2UubWF0Y2goL0AoQ29uc29sZVNjcmlwdHxVaVNjcmlwdClcXCgvKT8uaW5kZXg7XG5cbiAgICAgICAgaWYgKCFzY3JpcHRNZXRhZGF0YUluZGV4IHx8IHNjcmlwdE1ldGFkYXRhSW5kZXggPCAwKSByZXR1cm47XG4gICAgICAgIGZvdW5kTWV0YWRhdGEgPSB0cnVlO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1lc2NhcGVcbiAgICAgICAgY29uc3QgcmVnZXggPSAvXFxAKENvbnNvbGVTY3JpcHR8VWlTY3JpcHQpXFwoW15cXCldKlxcKShcXC5bXlxcKV0qXFwpKT8vZ2k7XG4gICAgICAgIGNvbnN0IG1ldGFkYXRhRGVjb3JhdG9yTWF0Y2hlciA9IHNvdXJjZS5tYXRjaChyZWdleCk7XG4gICAgICAgIGlmIChtZXRhZGF0YURlY29yYXRvck1hdGNoZXIpIHtcbiAgICAgICAgICBtZXRhZGF0YUNvbnRlbnQgPSBtZXRhZGF0YURlY29yYXRvck1hdGNoZXIuYXQoMCkgYXMgc3RyaW5nO1xuICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwibWV0YWRhdGFDb250ZW50XCIsIG1ldGFkYXRhQ29udGVudCk7XG4gICAgICAgICAgY29uc3Qgc3RhcnRKc29uTWV0YWRhdGFJbmRleCA9IG1ldGFkYXRhQ29udGVudC5pbmRleE9mKFwie1wiKTtcbiAgICAgICAgICBjb25zdCBlbmRKc29uTWV0YWRhdGFJbmRleCA9IG1ldGFkYXRhQ29udGVudC5sYXN0SW5kZXhPZihcIn1cIik7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGFKc29uU3RyaW5nID0gbWV0YWRhdGFDb250ZW50LnN1YnN0cmluZyhzdGFydEpzb25NZXRhZGF0YUluZGV4LCBlbmRKc29uTWV0YWRhdGFJbmRleCArIDEpO1xuICAgICAgICAgIGNvbnN0IGNvbnRlbnRzID0gc291cmNlLnJlcGxhY2UobWV0YWRhdGFKc29uU3RyaW5nLCBcIlwiKTsgLy8gcmVtb3ZlIHRoZSBqc29uIG1ldGFkYXRhIGZyb20gc291cmNlXG4gICAgICAgICAgLy8gY29uc3QgY29udGVudHMgPSBzb3VyY2UucmVwbGFjZShyZWdleCwgXCJcIik7IC8vIHJlbW92ZSBAQ29uc29sZVNjcmlwdCh7Li4uLn0pIGZyb20gc291cmNlXG5cbiAgICAgICAgICAvLyBjb25zdCBjb250ZW50cyA9IHNvdXJjZS5yZXBsYWNlKHJlZ2V4LCBcIlwiKTtcbiAgICAgICAgICBjb25zdCBleHRlbnNpb24gPSBhcmdzLnBhdGguc3BsaXQoXCIuXCIpLnBvcCgpO1xuXG4gICAgICAgICAgY29uc3QgbG9hZGVyID0gZXh0ZW5zaW9uID09PSBcInRzeFwiID8gXCJ0c3hcIiA6IFwidHNcIjtcblxuICAgICAgICAgIHJldHVybiB7IGNvbnRlbnRzLCBsb2FkZXIgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH0pO1xuXG4gICAgICBidWlsZC5vbkVuZChhc3luYyAocmVzdWx0KSA9PiB7XG4gICAgICAgIGlmICghYnVpbGQuaW5pdGlhbE9wdGlvbnM/Lm91dGZpbGUgfHwgIWJ1aWxkLmluaXRpYWxPcHRpb25zPy5idW5kbGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFwiV3JvbmcgYnVpbGQgY29uZmlndXJhdGlvbi4gT3B0aW9ucyAnYnVuZGxlJyBtdXN0IGJlIGVuYWJsZWQgYW5kICdvdXRmaWxlJyBtdXN0IGJlIHNldC5cIik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFmb3VuZE1ldGFkYXRhKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIlNjcmlwdE1ldGFkYXRhIGRlY29yYXRvciBub3QgZm91bmQuXCIpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQuZXJyb3JzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBidWlsZGluZy4gU2NyaXB0IE1ldGFkYXRhIGNhbm5vdCBiZSBhZGRlZCB0byBmaW5hbCBzY3JpcHQuXCIpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZpbGVDb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlKGJ1aWxkLmluaXRpYWxPcHRpb25zLm91dGZpbGUpO1xuICAgICAgICBjb25zdCBzY3JpcHRNZXRhZGF0YVN0cmluZyA9IGdldFNjcmlwdE1ldGFkYXRhU3RyaW5nKG1ldGFkYXRhQ29udGVudCk7XG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZShidWlsZC5pbml0aWFsT3B0aW9ucy5vdXRmaWxlLCBgJHtzY3JpcHRNZXRhZGF0YVN0cmluZ31cXG5cXG4ke2ZpbGVDb250ZW50cy50b1N0cmluZygpfWApO1xuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2NyaXB0TWV0YWRhdGFTdHJpbmcoc2NyaXB0TWV0YWRhdGFGdW5jdGlvbkNhbGxTdHJpbmc6IHN0cmluZykge1xuICBzY3JpcHRNZXRhZGF0YUZ1bmN0aW9uQ2FsbFN0cmluZyA9IHNjcmlwdE1ldGFkYXRhRnVuY3Rpb25DYWxsU3RyaW5nLnRyaW0oKTtcbiAgY29uc3Qgc3RhcnRKc29uTWV0YWRhdGFJbmRleCA9IHNjcmlwdE1ldGFkYXRhRnVuY3Rpb25DYWxsU3RyaW5nLmluZGV4T2YoXCJ7XCIpO1xuICBjb25zdCBlbmRKc29uTWV0YWRhdGFJbmRleCA9IHNjcmlwdE1ldGFkYXRhRnVuY3Rpb25DYWxsU3RyaW5nLmxhc3RJbmRleE9mKFwifVwiKTtcbiAgaWYgKHN0YXJ0SnNvbk1ldGFkYXRhSW5kZXggPCAwIHx8IGVuZEpzb25NZXRhZGF0YUluZGV4IDwgMCkge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgY29uc3QganNvbk1ldGFkYXRhU3RyaW5nID0gc2NyaXB0TWV0YWRhdGFGdW5jdGlvbkNhbGxTdHJpbmcuc3Vic3RyaW5nKFxuICAgIHN0YXJ0SnNvbk1ldGFkYXRhSW5kZXgsXG4gICAgZW5kSnNvbk1ldGFkYXRhSW5kZXggKyAxLFxuICApO1xuXG4gIGNvbnN0IG1ldGFkYXRhT2JqZWN0ID0gSlNPTjUucGFyc2UoanNvbk1ldGFkYXRhU3RyaW5nKTtcblxuICBjb25zdCB0YWcgPSBcIi8vID09VXNlclNjcmlwdD09XCI7XG4gIGNvbnN0IHRhZ0VuZCA9IFwiLy8gPT0vVXNlclNjcmlwdD09XCI7XG4gIGNvbnN0IGhlYWRlcnNBcnIgPSBbXTtcblxuICBjb25zdCBzcGFjZXMgPSAxMztcbiAgZm9yIChjb25zdCBrZXkgaW4gbWV0YWRhdGFPYmplY3QpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShtZXRhZGF0YU9iamVjdFtrZXldKSkge1xuICAgICAgbWV0YWRhdGFPYmplY3Rba2V5XS5mb3JFYWNoKChpdGVtOiB1bmtub3duKSA9PiB7XG4gICAgICAgIGhlYWRlcnNBcnIucHVzaChgJHtrZXkucGFkRW5kKHNwYWNlcywgXCIgXCIpfSR7aXRlbX1gKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBoZWFkZXJzQXJyLnB1c2goYCR7a2V5LnBhZEVuZChzcGFjZXMsIFwiIFwiKX0ke21ldGFkYXRhT2JqZWN0W2tleV19YCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgaGVhZGVycyA9IGhlYWRlcnNBcnIubWFwKChoKSA9PiBgLy8gJHtofWApLmpvaW4oXCJcXG5cIik7XG4gIHJldHVybiBgJHt0YWd9XFxuJHtoZWFkZXJzfVxcbiR7dGFnRW5kfWA7XG59XG4iLCAiaW1wb3J0IHsgUGx1Z2luIH0gZnJvbSBcImVzYnVpbGRcIjtcbmltcG9ydCB7IGFwcGVuZEZpbGUsIHJlYWRGaWxlIH0gZnJvbSBcImZzL3Byb21pc2VzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiB4TW9ua2V5U3R5bGVzUGx1Z2luKCk6IFBsdWdpbiB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogXCJ4bW9ua2V5LXN0eWxlcy1wbHVnaW5cIixcbiAgICBzZXR1cChidWlsZCkge1xuICAgICAgYnVpbGQub25FbmQoYXN5bmMgKHJlc3VsdCkgPT4ge1xuICAgICAgICBpZiAoIWJ1aWxkLmluaXRpYWxPcHRpb25zPy5vdXRmaWxlIHx8ICFidWlsZC5pbml0aWFsT3B0aW9ucz8uYnVuZGxlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihcIldyb25nIGJ1aWxkIGNvbmZpZ3VyYXRpb24uIE9wdGlvbnMgJ2J1bmRsZScgbXVzdCBiZSBlbmFibGVkIGFuZCAnb3V0ZmlsZScgbXVzdCBiZSBzZXQuXCIpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcmVzdWx0Lm1ldGFmaWxlKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKFwiRVNCdWlsZCBtZXRhZmlsZSBub3QgZW5hYmxlZC4gU3R5bGUgYnVuZGxlIHNraXBwZWQuXCIpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvdXRwdXRzID0gcmVzdWx0Lm1ldGFmaWxlLm91dHB1dHM7XG4gICAgICAgIGxldCBjc3NGaWxlUGF0aCA9IFwiXCI7XG4gICAgICAgIGZvciAoY29uc3QgZmlsZSBpbiBvdXRwdXRzKSB7XG4gICAgICAgICAgY29uc3QgZXh0ID0gZmlsZS5zcGxpdChcIi5cIikucG9wKCk7XG4gICAgICAgICAgaWYgKGV4dCA9PT0gXCJjc3NcIikge1xuICAgICAgICAgICAgY3NzRmlsZVBhdGggPSBmaWxlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjc3NGaWxlUGF0aC5sZW5ndGgpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXCJbLV0gU3R5bGVTaGVldCBvdXRwdXQgc2tpcHBlZC5cIik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QganNPdXRGaWxlID0gYnVpbGQuaW5pdGlhbE9wdGlvbnMub3V0ZmlsZTtcblxuICAgICAgICBjb25zdCBjc3NDb250ZW50cyA9IChhd2FpdCByZWFkRmlsZShjc3NGaWxlUGF0aCkpLnRvU3RyaW5nKCk7XG4gICAgICAgIGFwcGVuZEZpbGUoanNPdXRGaWxlLCBgXFxuR00uYWRkU3R5bGUoXCJcXFxcXFxuJHtjc3NDb250ZW50cy50cmltKCl9XFxcXFxcblwiKTtgKTtcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59XG4iLCAiaW1wb3J0IHsgUGx1Z2luIH0gZnJvbSBcImVzYnVpbGRcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHhNb25rZXlPdXRwdXRTdGF0c1BsdWdpbigpOiBQbHVnaW4ge1xuICByZXR1cm4ge1xuICAgIG5hbWU6IFwieG1vbmtleS1vdXRwdXQtc3RhdHMtcGx1Z2luXCIsXG4gICAgc2V0dXAoYnVpbGQpIHtcbiAgICAgIGJ1aWxkLm9uRW5kKGFzeW5jIChyZXN1bHQpID0+IHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgY29uc3Qgb3V0cHV0cyA9IHJlc3VsdC5tZXRhZmlsZT8ub3V0cHV0cyBhcyBhbnk7XG4gICAgICAgIGNvbnN0IG91dHB1dFRvdGFsID0gT2JqZWN0LmtleXMob3V0cHV0cykucmVkdWNlKChwcmV2LCBjdXIpID0+IHByZXYgKyBvdXRwdXRzW2N1cl0uYnl0ZXMsIDApO1xuICAgICAgICBjb25zdCBidW5kbGVUb3RhbCA9IGh1bWFuRmlsZVNpemUob3V0cHV0VG90YWwpO1xuICAgICAgICBjb25zb2xlLmxvZyhcIlsqXSBCdW5kbGUgdG90YWw6XCIsIGJ1bmRsZVRvdGFsKTtcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIGh1bWFuRmlsZVNpemUoc2l6ZTogbnVtYmVyKSB7XG4gIGNvbnN0IGkgPSBzaXplID09IDAgPyAwIDogTWF0aC5mbG9vcihNYXRoLmxvZyhzaXplKSAvIE1hdGgubG9nKDEwMjQpKTtcbiAgcmV0dXJuIChzaXplIC8gTWF0aC5wb3coMTAyNCwgaSkpLnRvRml4ZWQoMSkgKyBcIlwiICsgW1wiYlwiLCBcImtCXCIsIFwiTUJcIiwgXCJHQlwiLCBcIlRCXCJdW2ldO1xufVxuIiwgImltcG9ydCB7IGJ1aWxkWG1vbmtleVNjcmlwdCB9IGZyb20gXCIuL2VzYnVpbGQvYnVpbGQuanNcIjtcblxuY29uc3QgZW50cnlGaWxlID0gcHJvY2Vzcy5hcmd2WzJdO1xuXG5pZiAoIWVudHJ5RmlsZSkge1xuICBjb25zb2xlLmVycm9yKGBObyBlbnRyeWZpbGUgc3BlY2lmaWVkLiBUcnkgYWRkaW5nIHRoZSBzY3JpcHQgdG8gYnVpbGQgaW4gdGhlIGFyZ3VtZW50LmApO1xuICBjb25zb2xlLmVycm9yKGBFeGFtcGxlOiBucG0gcnVuIGJ1aWxkIHNyYy9leGFtcGxlLXNjcmlwdC50c2ApO1xuICBwcm9jZXNzLmV4aXQoMSk7XG59XG5cbmJ1aWxkWG1vbmtleVNjcmlwdChlbnRyeUZpbGUpO1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsY0FBeUI7QUFDekIsaUNBQTJCOzs7QUNBM0Isc0JBQW9DO0FBQ3BDLG1CQUFrQjtBQUVYLFNBQVMsNkJBQXFDO0FBQ25ELFNBQU87QUFBQSxJQUNMLE1BQU07QUFBQSxJQUNOLE1BQU1BLFFBQU87QUFDWCxVQUFJLGdCQUFnQjtBQUNwQixVQUFJLGtCQUFrQjtBQUV0QixNQUFBQSxPQUFNLE9BQU8sRUFBRSxRQUFRLGFBQWEsV0FBVyxPQUFPLEdBQUcsT0FBTyxTQUFTO0FBQ3ZFLFlBQUk7QUFBZTtBQUNuQixjQUFNLFNBQVMsVUFBTSwwQkFBUyxLQUFLLE1BQU0sTUFBTTtBQUMvQyxjQUFNLHNCQUFzQixPQUFPLE1BQU0sNkJBQTZCLEdBQUc7QUFFekUsWUFBSSxDQUFDLHVCQUF1QixzQkFBc0I7QUFBRztB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QU8sS0FBSyxJQUFJLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxLQUFLLE1BQU0sTUFBTSxNQUFNLElBQUksRUFBRSxDQUFDO0FBQ3JGOzs7QUhkQSxlQUFzQixtQkFBbUIsZ0JBQXdCO0FBRS9ELFFBQU1DLGFBQVk7QUFDbEIsVUFBUSxLQUFLLG1CQUFtQkEsVUFBUyxHQUFHO0FBRTVDLFFBQWMsY0FBTTtBQUFBLElBQ2xCLGFBQWEsQ0FBQ0EsVUFBUztBQUFBLElBQ3ZCLFNBQVM7QUFBQSxJQUNULFFBQVE7QUFBQSxJQUNSLGFBQWE7QUFBQSxJQUNiLFFBQVEsUUFBUSxJQUFJLFFBQVEsUUFBUTtBQUFBLElBQ3BDLFVBQVU7QUFBQSxJQUNWLFFBQVE7QUFBQTtBQUFBLElBRVIsV0FBVztBQUFBLElBQ1gsV0FBVztBQUFBLElBQ1gsVUFBVTtBQUFBLElBQ1YsVUFBVTtBQUFBLElBQ1YsU0FBUztBQUFBLE1BQ1AsMkJBQTJCO0FBQUE7QUFBQSxVQUUzQix1Q0FBVyxFQUFFLE9BQU8sYUFBYSxDQUFDO0FBQUEsTUFDbEMsb0JBQW9CO0FBQUEsTUFDcEIseUJBQXlCO0FBQUEsSUFDM0I7QUFBQSxFQUNGLENBQUM7QUFDSDs7O0FJOUJBLElBQU0sWUFBWSxRQUFRLEtBQUssQ0FBQztBQUVoQyxJQUFJLENBQUMsV0FBVztBQUNkLFVBQVEsTUFBTSx5RUFBeUU7QUFDdkYsVUFBUSxNQUFNLDhDQUE4QztBQUM1RCxVQUFRLEtBQUssQ0FBQztBQUNoQjtBQUVBLG1CQUFtQixTQUFTOyIsCiAgIm5hbWVzIjogWyJidWlsZCIsICJKU09ONSIsICJpbXBvcnRfcHJvbWlzZXMiLCAiYnVpbGQiLCAiYnVpbGQiLCAiZW50cnlGaWxlIl0KfQo=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildXmonkeyScript(scriptBasePath: string): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as esbuild from "esbuild";
|
|
2
|
+
import { sassPlugin } from "esbuild-sass-plugin";
|
|
3
|
+
import { xMonkeyStripMetadataPlugin } from "./plugins/xmonkey-strip-metadata-plugin.js";
|
|
4
|
+
import { xMonkeyStylesPlugin } from "./plugins/xmonkey-styles-plugin.js";
|
|
5
|
+
import { xMonkeyOutputStatsPlugin } from "./plugins/xmonkey-output-stats-plugin.js";
|
|
6
|
+
export async function buildXmonkeyScript(scriptBasePath) {
|
|
7
|
+
const entryFile = scriptBasePath;
|
|
8
|
+
console.info(`Building file: '${entryFile}'`);
|
|
9
|
+
await esbuild.build({
|
|
10
|
+
entryPoints: [entryFile],
|
|
11
|
+
outfile: "dist/index.js",
|
|
12
|
+
bundle: true,
|
|
13
|
+
treeShaking: true,
|
|
14
|
+
minify: process.env.DEBUG ? false : true,
|
|
15
|
+
platform: "browser",
|
|
16
|
+
format: "iife",
|
|
17
|
+
sourcemap: false,
|
|
18
|
+
keepNames: true,
|
|
19
|
+
logLevel: "info",
|
|
20
|
+
metafile: true,
|
|
21
|
+
plugins: [
|
|
22
|
+
xMonkeyStripMetadataPlugin(),
|
|
23
|
+
sassPlugin({ style: "compressed" }),
|
|
24
|
+
xMonkeyStylesPlugin(),
|
|
25
|
+
xMonkeyOutputStatsPlugin(),
|
|
26
|
+
],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function xMonkeyOutputStatsPlugin() {
|
|
2
|
+
return {
|
|
3
|
+
name: "xmonkey-output-stats-plugin",
|
|
4
|
+
setup(build) {
|
|
5
|
+
build.onEnd(async (result) => {
|
|
6
|
+
const outputs = result.metafile?.outputs;
|
|
7
|
+
const outputTotal = Object.keys(outputs).reduce((prev, cur) => prev + outputs[cur].bytes, 0);
|
|
8
|
+
const bundleTotal = humanFileSize(outputTotal);
|
|
9
|
+
console.log("[*] Bundle total:", bundleTotal);
|
|
10
|
+
});
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function humanFileSize(size) {
|
|
15
|
+
const i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
|
|
16
|
+
return (size / Math.pow(1024, i)).toFixed(1) + "" + ["b", "kB", "MB", "GB", "TB"][i];
|
|
17
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { readFile, writeFile } from "fs/promises";
|
|
2
|
+
import JSON5 from "json5";
|
|
3
|
+
export function xMonkeyStripMetadataPlugin() {
|
|
4
|
+
return {
|
|
5
|
+
name: "xmonkey-strip-metadata-plugin",
|
|
6
|
+
setup(build) {
|
|
7
|
+
let foundMetadata = false;
|
|
8
|
+
let metadataContent = "";
|
|
9
|
+
build.onLoad({ filter: /.(ts|tsx)/, namespace: "file" }, async (args) => {
|
|
10
|
+
if (foundMetadata)
|
|
11
|
+
return;
|
|
12
|
+
const source = await readFile(args.path, "utf8");
|
|
13
|
+
const scriptMetadataIndex = source.match(/@(ConsoleScript|UiScript)\(/)?.index;
|
|
14
|
+
if (!scriptMetadataIndex || scriptMetadataIndex < 0)
|
|
15
|
+
return;
|
|
16
|
+
foundMetadata = true;
|
|
17
|
+
const regex = /\@(ConsoleScript|UiScript)\([^\)]*\)(\.[^\)]*\))?/gi;
|
|
18
|
+
const metadataDecoratorMatcher = source.match(regex);
|
|
19
|
+
if (metadataDecoratorMatcher) {
|
|
20
|
+
metadataContent = metadataDecoratorMatcher.at(0);
|
|
21
|
+
const startJsonMetadataIndex = metadataContent.indexOf("{");
|
|
22
|
+
const endJsonMetadataIndex = metadataContent.lastIndexOf("}");
|
|
23
|
+
const metadataJsonString = metadataContent.substring(startJsonMetadataIndex, endJsonMetadataIndex + 1);
|
|
24
|
+
const contents = source.replace(metadataJsonString, "");
|
|
25
|
+
const extension = args.path.split(".").pop();
|
|
26
|
+
const loader = extension === "tsx" ? "tsx" : "ts";
|
|
27
|
+
return { contents, loader };
|
|
28
|
+
}
|
|
29
|
+
return;
|
|
30
|
+
});
|
|
31
|
+
build.onEnd(async (result) => {
|
|
32
|
+
if (!build.initialOptions?.outfile || !build.initialOptions?.bundle) {
|
|
33
|
+
console.error("Wrong build configuration. Options 'bundle' must be enabled and 'outfile' must be set.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!foundMetadata) {
|
|
37
|
+
console.error("ScriptMetadata decorator not found.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (result.errors.length) {
|
|
41
|
+
console.error("Error building. Script Metadata cannot be added to final script.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const fileContents = await readFile(build.initialOptions.outfile);
|
|
45
|
+
const scriptMetadataString = getScriptMetadataString(metadataContent);
|
|
46
|
+
await writeFile(build.initialOptions.outfile, `${scriptMetadataString}\n\n${fileContents.toString()}`);
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function getScriptMetadataString(scriptMetadataFunctionCallString) {
|
|
52
|
+
scriptMetadataFunctionCallString = scriptMetadataFunctionCallString.trim();
|
|
53
|
+
const startJsonMetadataIndex = scriptMetadataFunctionCallString.indexOf("{");
|
|
54
|
+
const endJsonMetadataIndex = scriptMetadataFunctionCallString.lastIndexOf("}");
|
|
55
|
+
if (startJsonMetadataIndex < 0 || endJsonMetadataIndex < 0) {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
const jsonMetadataString = scriptMetadataFunctionCallString.substring(startJsonMetadataIndex, endJsonMetadataIndex + 1);
|
|
59
|
+
const metadataObject = JSON5.parse(jsonMetadataString);
|
|
60
|
+
const tag = "// ==UserScript==";
|
|
61
|
+
const tagEnd = "// ==/UserScript==";
|
|
62
|
+
const headersArr = [];
|
|
63
|
+
const spaces = 13;
|
|
64
|
+
for (const key in metadataObject) {
|
|
65
|
+
if (Array.isArray(metadataObject[key])) {
|
|
66
|
+
metadataObject[key].forEach((item) => {
|
|
67
|
+
headersArr.push(`${key.padEnd(spaces, " ")}${item}`);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
headersArr.push(`${key.padEnd(spaces, " ")}${metadataObject[key]}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const headers = headersArr.map((h) => `// ${h}`).join("\n");
|
|
75
|
+
return `${tag}\n${headers}\n${tagEnd}`;
|
|
76
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { appendFile, readFile } from "fs/promises";
|
|
2
|
+
export function xMonkeyStylesPlugin() {
|
|
3
|
+
return {
|
|
4
|
+
name: "xmonkey-styles-plugin",
|
|
5
|
+
setup(build) {
|
|
6
|
+
build.onEnd(async (result) => {
|
|
7
|
+
if (!build.initialOptions?.outfile || !build.initialOptions?.bundle) {
|
|
8
|
+
console.error("Wrong build configuration. Options 'bundle' must be enabled and 'outfile' must be set.");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (!result.metafile) {
|
|
12
|
+
console.warn("ESBuild metafile not enabled. Style bundle skipped.");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const outputs = result.metafile.outputs;
|
|
16
|
+
let cssFilePath = "";
|
|
17
|
+
for (const file in outputs) {
|
|
18
|
+
const ext = file.split(".").pop();
|
|
19
|
+
if (ext === "css") {
|
|
20
|
+
cssFilePath = file;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!cssFilePath.length) {
|
|
25
|
+
console.warn("[-] StyleSheet output skipped.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const jsOutFile = build.initialOptions.outfile;
|
|
29
|
+
const cssContents = (await readFile(cssFilePath)).toString();
|
|
30
|
+
appendFile(jsOutFile, `\nGM.addStyle("\\\n${cssContents.trim()}\\\n");`);
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback, useState, useEffect } from "preact/hooks";
|
|
2
|
+
export function useLocalStorage(key, defaultValue) {
|
|
3
|
+
return useStorage(key, defaultValue, window.localStorage);
|
|
4
|
+
}
|
|
5
|
+
export function useSessionStorage(key, defaultValue) {
|
|
6
|
+
return useStorage(key, defaultValue, window.sessionStorage);
|
|
7
|
+
}
|
|
8
|
+
function useStorage(key, defaultValue, storageObject) {
|
|
9
|
+
const [value, setValue] = useState(() => {
|
|
10
|
+
const jsonValue = storageObject.getItem(key);
|
|
11
|
+
if (jsonValue != null)
|
|
12
|
+
return JSON.parse(jsonValue);
|
|
13
|
+
if (typeof defaultValue === "function") {
|
|
14
|
+
return defaultValue();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return defaultValue;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (value === undefined)
|
|
22
|
+
return storageObject.removeItem(key);
|
|
23
|
+
storageObject.setItem(key, JSON.stringify(value));
|
|
24
|
+
}, [key, value, storageObject]);
|
|
25
|
+
const remove = useCallback(() => {
|
|
26
|
+
setValue(undefined);
|
|
27
|
+
}, []);
|
|
28
|
+
return [value, setValue, remove];
|
|
29
|
+
}
|
package/dist/index.d.ts
ADDED
|
File without changes
|
package/dist/index.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* https://gist.github.com/jonsuh/b2347347480105874cda110b2afc53f4 */
|
|
2
|
+
/* Flexbox
|
|
3
|
+
// ================================================== */
|
|
4
|
+
|
|
5
|
+
@use "variables" as vars;
|
|
6
|
+
##{vars.$xmonkey-wrapper} {
|
|
7
|
+
.d-f { display: flex !important; flex-direction: column; }
|
|
8
|
+
.d-if { display: inline-flex !important; flex-direction: column; }
|
|
9
|
+
|
|
10
|
+
/* Flex direction */
|
|
11
|
+
.fd-r { flex-direction: row; } /* Default */
|
|
12
|
+
.fd-rr { flex-direction: row-reverse; }
|
|
13
|
+
.fd-c { flex-direction: column; }
|
|
14
|
+
.fd-cr { flex-direction: column-reverse; }
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/* Flex wrap */
|
|
18
|
+
.fw-n { flex-wrap: nowrap; } /* Default */
|
|
19
|
+
.fw-w { flex-wrap: wrap; }
|
|
20
|
+
.fw-wr { flex-wrap: wrap-reverse; }
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/* Justify content */
|
|
24
|
+
.jc-fe { justify-content: flex-end; }
|
|
25
|
+
.jc-fs { justify-content: flex-start; } /* Default */
|
|
26
|
+
.jc-c { justify-content: center; }
|
|
27
|
+
.jc-sa { justify-content: space-around; }
|
|
28
|
+
.jc-sb { justify-content: space-between; }
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
/* Align items */
|
|
32
|
+
.ai-fs { align-items: flex-start; }
|
|
33
|
+
.ai-c { align-items: center; }
|
|
34
|
+
.ai-fe { align-items: flex-end; }
|
|
35
|
+
.ai-s { align-items: stretch; } /* Default */
|
|
36
|
+
.ai-b { align-items: baseline; }
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/* Flex grow */
|
|
40
|
+
.fg-0 { flex-grow: 0; } /* Default */
|
|
41
|
+
.fg-1 { flex-grow: 1; }
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/* Flex shrink */
|
|
45
|
+
.fs-0 { flex-shrink: 0; }
|
|
46
|
+
.fs-1 { flex-shrink: 1; } /* Default */
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
/* Flex basis */
|
|
50
|
+
.fb-a { flex-basis: auto; } /* Default */
|
|
51
|
+
.fb-0 { flex-basis: 0; }
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/* Align self */
|
|
55
|
+
.as-a { align-self: auto; } /* Default */
|
|
56
|
+
.as-fs { align-self: flex-start; }
|
|
57
|
+
.as-c { align-self: center; }
|
|
58
|
+
.as-fe { align-self: flex-end; }
|
|
59
|
+
.as-s { align-self: stretch; }
|
|
60
|
+
.as-b { align-self: baseline }
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
.noselect {
|
|
64
|
+
-webkit-touch-callout: none; /* iOS Safari */
|
|
65
|
+
-webkit-user-select: none; /* Safari */
|
|
66
|
+
-khtml-user-select: none; /* Konqueror HTML */
|
|
67
|
+
-moz-user-select: none; /* Old versions of Firefox */
|
|
68
|
+
-ms-user-select: none; /* Internet Explorer/Edge */
|
|
69
|
+
user-select: none; /* Non-prefixed version, currently
|
|
70
|
+
supported by Chrome, Edge, Opera and Firefox */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.hidden {display: none !important;}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
.w-10 { width: 10% }
|
|
78
|
+
.w-25 { width: 25% }
|
|
79
|
+
.w-50 { width: 50% }
|
|
80
|
+
.w-75 { width: 75% }
|
|
81
|
+
.w-100 { width: 100% }
|
|
82
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
@use "variables" as vars;
|
|
2
|
+
@use "colors";
|
|
3
|
+
|
|
4
|
+
##{vars.$xmonkey-wrapper} {
|
|
5
|
+
min-width: 200px;
|
|
6
|
+
width: 200px;
|
|
7
|
+
position: absolute;
|
|
8
|
+
top: 10px;
|
|
9
|
+
left: 10px;
|
|
10
|
+
background-color: rgba(colors.$bg, 0.99);
|
|
11
|
+
border-radius: vars.$border-radius;
|
|
12
|
+
z-index: 999999;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
|
|
15
|
+
font-family: vars.$font-family;
|
|
16
|
+
font-size: 12px;
|
|
17
|
+
* {
|
|
18
|
+
box-sizing: initial !important;
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
font-family: vars.$font-family;
|
|
21
|
+
color: colors.$white;
|
|
22
|
+
button {
|
|
23
|
+
color: colors.$black;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
pre {
|
|
27
|
+
overflow: auto;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
input,
|
|
31
|
+
select,
|
|
32
|
+
option,
|
|
33
|
+
textarea {
|
|
34
|
+
color: colors.$bg;
|
|
35
|
+
background-color: colors.$white !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
input[type="checkbox"] {
|
|
39
|
+
margin-left: 2px;
|
|
40
|
+
margin-right: 2px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
transition:
|
|
44
|
+
height 100ms ease-in-out,
|
|
45
|
+
width 100ms ease-in-out,
|
|
46
|
+
min-width 100ms ease-in-out,
|
|
47
|
+
min-height 100ms ease-in-out,
|
|
48
|
+
max-height 100ms ease-in-out,
|
|
49
|
+
max-width 100ms ease-in-out;
|
|
50
|
+
|
|
51
|
+
&:has(.minim) {
|
|
52
|
+
min-height: 15px !important;
|
|
53
|
+
min-width: 15px !important;
|
|
54
|
+
width: 15px !important;
|
|
55
|
+
height: 15px !important;
|
|
56
|
+
overflow: hidden !important;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.#{vars.$xmonkey-container} {
|
|
60
|
+
max-height: 1000px;
|
|
61
|
+
&:has(.#{vars.$xmonkey-header}) {
|
|
62
|
+
margin-top: 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.#{vars.$xmonkey-body} {
|
|
67
|
+
padding: 3px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.#{vars.$xmonkey-header} {
|
|
71
|
+
height: 15px;
|
|
72
|
+
line-height: 15px !important;
|
|
73
|
+
background-color: colors.$primary;
|
|
74
|
+
width: 100%;
|
|
75
|
+
// border-top-left-radius: vars.$border-radius;
|
|
76
|
+
// border-top-right-radius: vars.$border-radius;
|
|
77
|
+
.xmwr-x {
|
|
78
|
+
font-family: monospace !important;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
position: absolute;
|
|
81
|
+
right: 0px;
|
|
82
|
+
top: 0px;
|
|
83
|
+
font-weight: bold;
|
|
84
|
+
background-color: colors.$black;
|
|
85
|
+
padding: 0 5px;
|
|
86
|
+
height: 15px;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type ScriptInfo = {
|
|
2
|
+
"@name": string;
|
|
3
|
+
"@namespace": string;
|
|
4
|
+
"@match": string | string[];
|
|
5
|
+
"@version": string;
|
|
6
|
+
"@author": string;
|
|
7
|
+
"@description": string;
|
|
8
|
+
"@grant"?: string[];
|
|
9
|
+
[k: string]: unknown;
|
|
10
|
+
};
|
|
11
|
+
export type NonFunctionPropertyNames<T> = {
|
|
12
|
+
[K in keyof T]: T[K] extends Function ? never : K;
|
|
13
|
+
}[keyof T];
|
|
14
|
+
export type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
|
|
15
|
+
export type FunctionPropertyNames<T> = {
|
|
16
|
+
[K in keyof T]: T[K] extends Function ? K : never;
|
|
17
|
+
}[keyof T];
|
|
18
|
+
export type ClassConstructor<T> = {
|
|
19
|
+
new (..._: any[]): T;
|
|
20
|
+
};
|
|
21
|
+
export type Self<T> = ClassConstructor<T>;
|
|
22
|
+
export type AnyObject = {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
};
|
|
25
|
+
export type AnyType = string | number | boolean | AnyObject;
|
|
26
|
+
export type WithRequired<T, K extends keyof T> = T & {
|
|
27
|
+
[P in K]-?: T[P];
|
|
28
|
+
};
|
|
29
|
+
export type Complete<T> = {
|
|
30
|
+
[P in keyof Required<T>]: Pick<T, P> extends Required<Pick<T, P>> ? T[P] : T[P] | undefined;
|
|
31
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { h, render } from "preact";
|
|
2
|
+
import { XMonkeyWindowComponent } from "../x-monkey-window-component.js";
|
|
3
|
+
export function UiScript(_metadata) {
|
|
4
|
+
return function (_target) {
|
|
5
|
+
const scriptObject = new _target();
|
|
6
|
+
const rootComponent = xMonkeyWrapperElement();
|
|
7
|
+
render(h(XMonkeyWindowComponent, { title: scriptObject.title ?? "" }, scriptObject.render()), rootComponent);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function xMonkeyWrapperElement() {
|
|
11
|
+
const ID = "__xmwr";
|
|
12
|
+
let div = document.getElementById(ID);
|
|
13
|
+
if (div)
|
|
14
|
+
return div;
|
|
15
|
+
div = document.createElement("div");
|
|
16
|
+
div.id = ID;
|
|
17
|
+
document.body.appendChild(div);
|
|
18
|
+
return div;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getStorageKeyIdFromString(data: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { useSessionStorage } from "./hooks";
|
|
3
|
+
import { useMemo } from "preact/hooks";
|
|
4
|
+
import { getStorageKeyIdFromString } from "./utils/get-storage-key-id-from-string";
|
|
5
|
+
export function XMonkeyWindowComponent(props) {
|
|
6
|
+
const storageKey = useMemo(() => getStorageKeyIdFromString(props.title), [props.title]);
|
|
7
|
+
const [minimized, setMinimized] = useSessionStorage(storageKey, false);
|
|
8
|
+
function toggleMinimize() {
|
|
9
|
+
setMinimized(!minimized);
|
|
10
|
+
}
|
|
11
|
+
return (_jsxs("div", { className: `xmwr_c d-f fd-c ai-c jc-sb` + (minimized ? " minim" : ""), children: [_jsxs("div", { className: "xmwr-h w-100 m0 d-f fd-r jc-c bg-primary noselect", children: [_jsx("div", { className: "xmwr-title m0", children: props.title }), _jsx(MinimizeButton, { toggleMinimize: toggleMinimize, minimized: minimized })] }), _jsx("div", { className: "xmwr-b w-100 d-f jc-c", children: props.children })] }));
|
|
12
|
+
}
|
|
13
|
+
function MinimizeButton({ minimized, toggleMinimize }) {
|
|
14
|
+
const minimizeChar = minimized ? "+" : "-";
|
|
15
|
+
return (_jsx("div", { className: "xmwr-x m0", onClick: () => toggleMinimize(), children: minimizeChar }));
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -1,38 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukaskj/xmonkey",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.6",
|
|
4
4
|
"author": "lukaskj",
|
|
5
5
|
"license": "ISC",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"clean": "rimraf dist coverage .rollup.cache",
|
|
8
|
-
"prebuild": "pnpm run clean",
|
|
9
|
-
"prepublish": "pnpm run build",
|
|
10
|
-
"build:old": "node esbuild/build.mjs",
|
|
11
|
-
"build": "pnpm build:esm && pnpm build:bin && pnpm copy-styles",
|
|
12
|
-
"build:esm": "tsc -p tsconfig.build.json",
|
|
13
|
-
"build:cjs": "tsc -p tsconfig.build.json --module CommonJS --outDir dist/cjs",
|
|
14
|
-
"build:bin": "esbuild src/build.ts --platform=node --format=cjs --packages=external --bundle --sourcemap=inline --outfile=dist/build.js",
|
|
15
|
-
"build:prod": "pnpm run lint && pnpm run build",
|
|
16
|
-
"build:dev": "DEBUG=1 node esbuild/build.mjs",
|
|
17
|
-
"build:debug": "DEBUG=1 node esbuild/build.mjs",
|
|
18
|
-
"copy-styles": "cp -R src/styles/ dist/styles",
|
|
19
|
-
"dev": "nodemon",
|
|
20
|
-
"start": "tsx ./src/build.ts",
|
|
21
|
-
"format": "prettier --write src/",
|
|
22
|
-
"lint": "tsc --noEmit && eslint \"{src,apps,libs,test}/**/*.{ts,tsx}\" --fix",
|
|
23
|
-
"test": "jest --config ./jest.config.js --maxWorkers=1",
|
|
24
|
-
"test:watch": "pnpm run test -- --watch",
|
|
25
|
-
"test:cov": "pnpm run test -- --coverage",
|
|
26
|
-
"test:debug": "-- node --inspect=0.0.0.0:5001 -r ts-node/register node_modules/jest/bin/jest.js --runInBand --config ./jest.config.js",
|
|
27
|
-
"prepare": "husky"
|
|
28
|
-
},
|
|
29
6
|
"dependencies": {
|
|
30
7
|
"esbuild": "^0.20.1",
|
|
31
8
|
"esbuild-sass-plugin": "^3.1.0",
|
|
32
9
|
"json5": "^2.2.3",
|
|
33
10
|
"postcss": "^8.4.35",
|
|
34
11
|
"postcss-modules": "^6.0.0",
|
|
35
|
-
"preact": "^10.
|
|
12
|
+
"preact": "^10.26.9"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"preact": "^10.26.9"
|
|
36
16
|
},
|
|
37
17
|
"devDependencies": {
|
|
38
18
|
"@faker-js/faker": "^8.4.1",
|
|
@@ -48,12 +28,12 @@
|
|
|
48
28
|
"husky": "^9.0.11",
|
|
49
29
|
"jest": "^29.7.0",
|
|
50
30
|
"lint-staged": "^15.2.2",
|
|
51
|
-
"nodemon": "^3.1.
|
|
31
|
+
"nodemon": "^3.1.10",
|
|
52
32
|
"prettier": "^3.2.5",
|
|
53
33
|
"rimraf": "^5.0.5",
|
|
54
34
|
"ts-jest": "^29.1.2",
|
|
55
35
|
"tslib": "^2.6.2",
|
|
56
|
-
"tsx": "^4.
|
|
36
|
+
"tsx": "^4.20.3",
|
|
57
37
|
"typescript": "^5.3.0"
|
|
58
38
|
},
|
|
59
39
|
"engines": {
|
|
@@ -96,5 +76,27 @@
|
|
|
96
76
|
],
|
|
97
77
|
"bin": {
|
|
98
78
|
"xmonkey": "dist/build.js"
|
|
79
|
+
},
|
|
80
|
+
"scripts": {
|
|
81
|
+
"clean": "rimraf dist coverage .rollup.cache",
|
|
82
|
+
"prebuild": "pnpm run clean",
|
|
83
|
+
"prepublish": "pnpm run build",
|
|
84
|
+
"build:old": "node esbuild/build.mjs",
|
|
85
|
+
"build": "pnpm build:esm && pnpm build:bin && pnpm copy-styles",
|
|
86
|
+
"build:esm": "tsc -p tsconfig.build.json",
|
|
87
|
+
"build:cjs": "tsc -p tsconfig.build.json --module CommonJS --outDir dist/cjs",
|
|
88
|
+
"build:bin": "esbuild src/build.ts --platform=node --format=cjs --packages=external --bundle --sourcemap=inline --outfile=dist/build.js",
|
|
89
|
+
"build:prod": "pnpm run lint && pnpm run build",
|
|
90
|
+
"build:dev": "DEBUG=1 node esbuild/build.mjs",
|
|
91
|
+
"build:debug": "DEBUG=1 node esbuild/build.mjs",
|
|
92
|
+
"copy-styles": "cp -R src/styles/ dist/styles",
|
|
93
|
+
"dev": "nodemon",
|
|
94
|
+
"start": "tsx ./src/build.ts",
|
|
95
|
+
"format": "prettier --write src/",
|
|
96
|
+
"lint": "tsc --noEmit && eslint \"{src,apps,libs,test}/**/*.{ts,tsx}\" --fix",
|
|
97
|
+
"test": "jest --config ./jest.config.js --maxWorkers=1",
|
|
98
|
+
"test:watch": "pnpm run test -- --watch",
|
|
99
|
+
"test:cov": "pnpm run test -- --coverage",
|
|
100
|
+
"test:debug": "-- node --inspect=0.0.0.0:5001 -r ts-node/register node_modules/jest/bin/jest.js --runInBand --config ./jest.config.js"
|
|
99
101
|
}
|
|
100
|
-
}
|
|
102
|
+
}
|