@jsprismarine/mcfunction 0.0.0-stage → 0.16.0-unstable-20261029132853

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +373 -0
  3. package/README.md +181 -2
  4. package/dist/compile.cjs.cjs +166 -0
  5. package/dist/compile.d.ts +91 -0
  6. package/dist/compile.d.ts.map +1 -0
  7. package/dist/compile.es.js +162 -0
  8. package/dist/diagnostics.cjs.cjs +19 -0
  9. package/dist/diagnostics.d.ts +62 -0
  10. package/dist/diagnostics.d.ts.map +1 -0
  11. package/dist/diagnostics.es.js +17 -0
  12. package/dist/executor.cjs.cjs +302 -0
  13. package/dist/executor.d.ts +140 -0
  14. package/dist/executor.d.ts.map +1 -0
  15. package/dist/executor.es.js +298 -0
  16. package/dist/identifiers.cjs.cjs +79 -0
  17. package/dist/identifiers.d.ts +44 -0
  18. package/dist/identifiers.d.ts.map +1 -0
  19. package/dist/identifiers.es.js +72 -0
  20. package/dist/index.cjs.cjs +36 -0
  21. package/dist/index.d.ts +10 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.es.js +10 -0
  24. package/dist/macro.cjs.cjs +119 -0
  25. package/dist/macro.d.ts +59 -0
  26. package/dist/macro.d.ts.map +1 -0
  27. package/dist/macro.es.js +115 -0
  28. package/dist/parse.cjs.cjs +107 -0
  29. package/dist/parse.d.ts +40 -0
  30. package/dist/parse.d.ts.map +1 -0
  31. package/dist/parse.es.js +104 -0
  32. package/dist/registry.cjs.cjs +135 -0
  33. package/dist/registry.d.ts +53 -0
  34. package/dist/registry.d.ts.map +1 -0
  35. package/dist/registry.es.js +132 -0
  36. package/dist/runner.cjs.cjs +42 -0
  37. package/dist/runner.d.ts +83 -0
  38. package/dist/runner.d.ts.map +1 -0
  39. package/dist/runner.es.js +40 -0
  40. package/dist/tags.cjs.cjs +113 -0
  41. package/dist/tags.d.ts +70 -0
  42. package/dist/tags.d.ts.map +1 -0
  43. package/dist/tags.es.js +108 -0
  44. package/package.json +61 -3
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ // src/macro.ts
4
+ var VARIABLE_PATTERN = /^[A-Za-z0-9_]+$/;
5
+ /**
6
+ * The most fraction digits a non-integer macro argument prints. Java formats
7
+ * the value with a `DecimalFormat` under `Locale.ROOT`; Mojang does not state
8
+ * the digit count, so this is a choice that keeps every double exactly
9
+ * representable in decimal form rather than a confirmed vanilla number.
10
+ */
11
+ var MAX_FRACTION_DIGITS = 17;
12
+ /**
13
+ * Compiles one macro line into a reusable template.
14
+ *
15
+ * `$` is literal unless it is followed by `(`, which is the only escape the
16
+ * format has. A line marked as a macro but carrying no substitution is an
17
+ * error, as is an unterminated `$(` or a name outside letters, digits and `_`.
18
+ */
19
+ var compileMacroLine = (command) => {
20
+ const segments = [];
21
+ const variables = [];
22
+ let literal = "";
23
+ for (let index = 0; index < command.length; index += 1) {
24
+ if (command[index] !== "$" || command[index + 1] !== "(") {
25
+ literal += command[index];
26
+ continue;
27
+ }
28
+ const close = command.indexOf(")", index + 2);
29
+ if (close === -1) return {
30
+ ok: false,
31
+ message: "unterminated macro variable"
32
+ };
33
+ const variable = command.slice(index + 2, close);
34
+ if (!VARIABLE_PATTERN.test(variable)) return {
35
+ ok: false,
36
+ message: `invalid macro variable name '${variable}'`
37
+ };
38
+ if (literal.length > 0) {
39
+ segments.push({ text: literal });
40
+ literal = "";
41
+ }
42
+ segments.push({ variable });
43
+ if (!variables.includes(variable)) variables.push(variable);
44
+ index = close;
45
+ }
46
+ if (variables.length === 0) return {
47
+ ok: false,
48
+ message: "no variables in macro"
49
+ };
50
+ if (literal.length > 0) segments.push({ text: literal });
51
+ return {
52
+ ok: true,
53
+ template: {
54
+ segments,
55
+ variables
56
+ }
57
+ };
58
+ };
59
+ /**
60
+ * Fills a compiled macro line from an argument compound.
61
+ *
62
+ * @returns The command to parse, or the reason the call cannot be instantiated.
63
+ */
64
+ var substituteMacro = (template, args) => {
65
+ let command = "";
66
+ for (const segment of template.segments) {
67
+ if ("text" in segment) {
68
+ command += segment.text;
69
+ continue;
70
+ }
71
+ const value = args[segment.variable];
72
+ if (value === void 0 || value === null) return {
73
+ ok: false,
74
+ message: `the macro arguments have no entry for '${segment.variable}'`
75
+ };
76
+ command += renderMacroValue(value);
77
+ }
78
+ return {
79
+ ok: true,
80
+ command
81
+ };
82
+ };
83
+ /**
84
+ * Renders one argument the way a substitution inserts it: a string goes in
85
+ * raw, with no quoting and no escaping, so a value carrying quotes can produce
86
+ * a command that no longer parses. Numbers lose the type suffix they would
87
+ * carry in NBT, matching the 1.20.2 fix. A compound or list becomes SNBT,
88
+ * where suffixes are back because the text is NBT again.
89
+ */
90
+ var renderMacroValue = (value) => {
91
+ if (typeof value === "string") return value;
92
+ if (typeof value === "number") return renderNumber(value);
93
+ if (typeof value === "bigint") return value.toString();
94
+ if (typeof value === "boolean") return value ? "1" : "0";
95
+ return renderSnbt(value);
96
+ };
97
+ /** Prints a number in plain decimal, never in exponent form and never with a suffix. */
98
+ var renderNumber = (value) => {
99
+ if (!Number.isFinite(value)) return String(value);
100
+ if (Number.isInteger(value) && Math.abs(value) < Number.MAX_SAFE_INTEGER) return value.toFixed(0);
101
+ const fixed = value.toFixed(MAX_FRACTION_DIGITS);
102
+ return fixed.includes(".") ? fixed.replace(/0+$/, "").replace(/\.$/, "") : fixed;
103
+ };
104
+ /** Renders a nested value as SNBT, the text form a command argument expects. */
105
+ var renderSnbt = (value) => {
106
+ if (value === null || value === void 0) return "{}";
107
+ if (typeof value === "string") return `"${value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}"`;
108
+ if (typeof value === "number") return renderNumber(value);
109
+ if (typeof value === "bigint") return `${value}L`;
110
+ if (typeof value === "boolean") return value ? "1b" : "0b";
111
+ if (Array.isArray(value)) return `[${value.map(renderSnbt).join(",")}]`;
112
+ if (typeof value === "object") return `{${Object.entries(value).map(([key, entry]) => `${key}:${renderSnbt(entry)}`).join(",")}}`;
113
+ return String(value);
114
+ };
115
+ exports.compileMacroLine = compileMacroLine;
116
+ exports.renderMacroValue = renderMacroValue;
117
+ exports.substituteMacro = substituteMacro;
118
+
119
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFjcm8uY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi9zcmMvbWFjcm8udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNYWNybyBsaW5lcyBhbmQgdGhlaXIgYCQodmFyaWFibGUpYCBzdWJzdGl0dXRpb25zLCBhcyAxLjIwLjIgZGVmaW5lZCB0aGVtLlxuICogQSBtYWNybyBsaW5lIGlzIGNvbXBpbGVkIG9uY2UgaW50byBhIHRlbXBsYXRlIG9mIGxpdGVyYWwgdGV4dCBhbmQgdmFyaWFibGVcbiAqIGhvbGVzOyBhIGNhbGwgZmlsbHMgdGhlIGhvbGVzIGZyb20gYSBjb21wb3VuZCBvZiBhcmd1bWVudHMgYW5kIHRoZSByZXN1bHRpbmdcbiAqIGNvbW1hbmQgaXMgcGFyc2VkIGZyZXNoLCB3aGljaCBpcyB0aGUgY29zdCBhIG1hY3JvIGFkZHMgb3ZlciBhIHBsYWluIGxpbmUuXG4gKi9cblxuLyoqIFRoZSBjb21wb3VuZCBhIG1hY3JvIGNhbGwgc3Vic3RpdHV0ZXMgZnJvbS4gRXh0cmEgZW50cmllcyBhcmUgaWdub3JlZC4gKi9cbmV4cG9ydCB0eXBlIE1hY3JvQXJndW1lbnRzID0gUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+O1xuXG4vKiogT25lIHBpZWNlIG9mIGEgY29tcGlsZWQgbWFjcm8gbGluZTogbGl0ZXJhbCB0ZXh0LCBvciBhIGhvbGUgbmFtaW5nIGEgdmFyaWFibGUuICovXG5leHBvcnQgdHlwZSBNYWNyb1NlZ21lbnQgPSB7IHRleHQ6IHN0cmluZyB9IHwgeyB2YXJpYWJsZTogc3RyaW5nIH07XG5cbi8qKiBBIG1hY3JvIGxpbmUgY29tcGlsZWQgaW50byB0aGUgcGllY2VzIGEgY2FsbCBjb25jYXRlbmF0ZXMuICovXG5leHBvcnQgaW50ZXJmYWNlIE1hY3JvVGVtcGxhdGUge1xuICAgIHNlZ21lbnRzOiByZWFkb25seSBNYWNyb1NlZ21lbnRbXTtcbiAgICAvKiogRXZlcnkgdmFyaWFibGUgdGhlIGxpbmUgc3Vic3RpdHV0ZXMsIG9uY2UgZWFjaCwgaW4gZmlyc3QtdXNlIG9yZGVyLiAqL1xuICAgIHZhcmlhYmxlczogcmVhZG9ubHkgc3RyaW5nW107XG59XG5cbi8qKiBUaGUgb3V0Y29tZSBvZiBjb21waWxpbmcgYSBtYWNybyBsaW5lLiAqL1xuZXhwb3J0IHR5cGUgTWFjcm9UZW1wbGF0ZVJlc3VsdCA9IHsgb2s6IHRydWU7IHRlbXBsYXRlOiBNYWNyb1RlbXBsYXRlIH0gfCB7IG9rOiBmYWxzZTsgbWVzc2FnZTogc3RyaW5nIH07XG5cbi8qKiBUaGUgb3V0Y29tZSBvZiBmaWxsaW5nIGEgdGVtcGxhdGUgZnJvbSBhbiBhcmd1bWVudCBjb21wb3VuZC4gKi9cbmV4cG9ydCB0eXBlIE1hY3JvU3Vic3RpdHV0aW9uUmVzdWx0ID0geyBvazogdHJ1ZTsgY29tbWFuZDogc3RyaW5nIH0gfCB7IG9rOiBmYWxzZTsgbWVzc2FnZTogc3RyaW5nIH07XG5cbmNvbnN0IFZBUklBQkxFX1BBVFRFUk4gPSAvXltBLVphLXowLTlfXSskLztcblxuLyoqXG4gKiBUaGUgbW9zdCBmcmFjdGlvbiBkaWdpdHMgYSBub24taW50ZWdlciBtYWNybyBhcmd1bWVudCBwcmludHMuIEphdmEgZm9ybWF0c1xuICogdGhlIHZhbHVlIHdpdGggYSBgRGVjaW1hbEZvcm1hdGAgdW5kZXIgYExvY2FsZS5ST09UYDsgTW9qYW5nIGRvZXMgbm90IHN0YXRlXG4gKiB0aGUgZGlnaXQgY291bnQsIHNvIHRoaXMgaXMgYSBjaG9pY2UgdGhhdCBrZWVwcyBldmVyeSBkb3VibGUgZXhhY3RseVxuICogcmVwcmVzZW50YWJsZSBpbiBkZWNpbWFsIGZvcm0gcmF0aGVyIHRoYW4gYSBjb25maXJtZWQgdmFuaWxsYSBudW1iZXIuXG4gKi9cbmNvbnN0IE1BWF9GUkFDVElPTl9ESUdJVFMgPSAxNztcblxuLyoqXG4gKiBDb21waWxlcyBvbmUgbWFjcm8gbGluZSBpbnRvIGEgcmV1c2FibGUgdGVtcGxhdGUuXG4gKlxuICogYCRgIGlzIGxpdGVyYWwgdW5sZXNzIGl0IGlzIGZvbGxvd2VkIGJ5IGAoYCwgd2hpY2ggaXMgdGhlIG9ubHkgZXNjYXBlIHRoZVxuICogZm9ybWF0IGhhcy4gQSBsaW5lIG1hcmtlZCBhcyBhIG1hY3JvIGJ1dCBjYXJyeWluZyBubyBzdWJzdGl0dXRpb24gaXMgYW5cbiAqIGVycm9yLCBhcyBpcyBhbiB1bnRlcm1pbmF0ZWQgYCQoYCBvciBhIG5hbWUgb3V0c2lkZSBsZXR0ZXJzLCBkaWdpdHMgYW5kIGBfYC5cbiAqL1xuZXhwb3J0IGNvbnN0IGNvbXBpbGVNYWNyb0xpbmUgPSAoY29tbWFuZDogc3RyaW5nKTogTWFjcm9UZW1wbGF0ZVJlc3VsdCA9PiB7XG4gICAgY29uc3Qgc2VnbWVudHM6IE1hY3JvU2VnbWVudFtdID0gW107XG4gICAgY29uc3QgdmFyaWFibGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBsaXRlcmFsID0gJyc7XG5cbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY29tbWFuZC5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgICAgaWYgKGNvbW1hbmRbaW5kZXhdICE9PSAnJCcgfHwgY29tbWFuZFtpbmRleCArIDFdICE9PSAnKCcpIHtcbiAgICAgICAgICAgIGxpdGVyYWwgKz0gY29tbWFuZFtpbmRleF07XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsb3NlID0gY29tbWFuZC5pbmRleE9mKCcpJywgaW5kZXggKyAyKTtcbiAgICAgICAgaWYgKGNsb3NlID09PSAtMSkgcmV0dXJuIHsgb2s6IGZhbHNlLCBtZXNzYWdlOiAndW50ZXJtaW5hdGVkIG1hY3JvIHZhcmlhYmxlJyB9O1xuXG4gICAgICAgIGNvbnN0IHZhcmlhYmxlID0gY29tbWFuZC5zbGljZShpbmRleCArIDIsIGNsb3NlKTtcbiAgICAgICAgaWYgKCFWQVJJQUJMRV9QQVRURVJOLnRlc3QodmFyaWFibGUpKSB7XG4gICAgICAgICAgICByZXR1cm4geyBvazogZmFsc2UsIG1lc3NhZ2U6IGBpbnZhbGlkIG1hY3JvIHZhcmlhYmxlIG5hbWUgJyR7dmFyaWFibGV9J2AgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsaXRlcmFsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHNlZ21lbnRzLnB1c2goeyB0ZXh0OiBsaXRlcmFsIH0pO1xuICAgICAgICAgICAgbGl0ZXJhbCA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHNlZ21lbnRzLnB1c2goeyB2YXJpYWJsZSB9KTtcbiAgICAgICAgaWYgKCF2YXJpYWJsZXMuaW5jbHVkZXModmFyaWFibGUpKSB2YXJpYWJsZXMucHVzaCh2YXJpYWJsZSk7XG4gICAgICAgIGluZGV4ID0gY2xvc2U7XG4gICAgfVxuXG4gICAgaWYgKHZhcmlhYmxlcy5sZW5ndGggPT09IDApIHJldHVybiB7IG9rOiBmYWxzZSwgbWVzc2FnZTogJ25vIHZhcmlhYmxlcyBpbiBtYWNybycgfTtcbiAgICBpZiAobGl0ZXJhbC5sZW5ndGggPiAwKSBzZWdtZW50cy5wdXNoKHsgdGV4dDogbGl0ZXJhbCB9KTtcblxuICAgIHJldHVybiB7IG9rOiB0cnVlLCB0ZW1wbGF0ZTogeyBzZWdtZW50cywgdmFyaWFibGVzIH0gfTtcbn07XG5cbi8qKlxuICogRmlsbHMgYSBjb21waWxlZCBtYWNybyBsaW5lIGZyb20gYW4gYXJndW1lbnQgY29tcG91bmQuXG4gKlxuICogQHJldHVybnMgVGhlIGNvbW1hbmQgdG8gcGFyc2UsIG9yIHRoZSByZWFzb24gdGhlIGNhbGwgY2Fubm90IGJlIGluc3RhbnRpYXRlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IHN1YnN0aXR1dGVNYWNybyA9ICh0ZW1wbGF0ZTogTWFjcm9UZW1wbGF0ZSwgYXJnczogTWFjcm9Bcmd1bWVudHMpOiBNYWNyb1N1YnN0aXR1dGlvblJlc3VsdCA9PiB7XG4gICAgbGV0IGNvbW1hbmQgPSAnJztcblxuICAgIGZvciAoY29uc3Qgc2VnbWVudCBvZiB0ZW1wbGF0ZS5zZWdtZW50cykge1xuICAgICAgICBpZiAoJ3RleHQnIGluIHNlZ21lbnQpIHtcbiAgICAgICAgICAgIGNvbW1hbmQgKz0gc2VnbWVudC50ZXh0O1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB2YWx1ZSA9IGFyZ3Nbc2VnbWVudC52YXJpYWJsZV07XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4geyBvazogZmFsc2UsIG1lc3NhZ2U6IGB0aGUgbWFjcm8gYXJndW1lbnRzIGhhdmUgbm8gZW50cnkgZm9yICcke3NlZ21lbnQudmFyaWFibGV9J2AgfTtcbiAgICAgICAgfVxuICAgICAgICBjb21tYW5kICs9IHJlbmRlck1hY3JvVmFsdWUodmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiB7IG9rOiB0cnVlLCBjb21tYW5kIH07XG59O1xuXG4vKipcbiAqIFJlbmRlcnMgb25lIGFyZ3VtZW50IHRoZSB3YXkgYSBzdWJzdGl0dXRpb24gaW5zZXJ0cyBpdDogYSBzdHJpbmcgZ29lcyBpblxuICogcmF3LCB3aXRoIG5vIHF1b3RpbmcgYW5kIG5vIGVzY2FwaW5nLCBzbyBhIHZhbHVlIGNhcnJ5aW5nIHF1b3RlcyBjYW4gcHJvZHVjZVxuICogYSBjb21tYW5kIHRoYXQgbm8gbG9uZ2VyIHBhcnNlcy4gTnVtYmVycyBsb3NlIHRoZSB0eXBlIHN1ZmZpeCB0aGV5IHdvdWxkXG4gKiBjYXJyeSBpbiBOQlQsIG1hdGNoaW5nIHRoZSAxLjIwLjIgZml4LiBBIGNvbXBvdW5kIG9yIGxpc3QgYmVjb21lcyBTTkJULFxuICogd2hlcmUgc3VmZml4ZXMgYXJlIGJhY2sgYmVjYXVzZSB0aGUgdGV4dCBpcyBOQlQgYWdhaW4uXG4gKi9cbmV4cG9ydCBjb25zdCByZW5kZXJNYWNyb1ZhbHVlID0gKHZhbHVlOiB1bmtub3duKTogc3RyaW5nID0+IHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykgcmV0dXJuIHZhbHVlO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSByZXR1cm4gcmVuZGVyTnVtYmVyKHZhbHVlKTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYmlnaW50JykgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSByZXR1cm4gdmFsdWUgPyAnMScgOiAnMCc7XG4gICAgcmV0dXJuIHJlbmRlclNuYnQodmFsdWUpO1xufTtcblxuLyoqIFByaW50cyBhIG51bWJlciBpbiBwbGFpbiBkZWNpbWFsLCBuZXZlciBpbiBleHBvbmVudCBmb3JtIGFuZCBuZXZlciB3aXRoIGEgc3VmZml4LiAqL1xuY29uc3QgcmVuZGVyTnVtYmVyID0gKHZhbHVlOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICAgIGlmICghTnVtYmVyLmlzRmluaXRlKHZhbHVlKSkgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gICAgaWYgKE51bWJlci5pc0ludGVnZXIodmFsdWUpICYmIE1hdGguYWJzKHZhbHVlKSA8IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKSByZXR1cm4gdmFsdWUudG9GaXhlZCgwKTtcblxuICAgIGNvbnN0IGZpeGVkID0gdmFsdWUudG9GaXhlZChNQVhfRlJBQ1RJT05fRElHSVRTKTtcbiAgICByZXR1cm4gZml4ZWQuaW5jbHVkZXMoJy4nKSA/IGZpeGVkLnJlcGxhY2UoLzArJC8sICcnKS5yZXBsYWNlKC9cXC4kLywgJycpIDogZml4ZWQ7XG59O1xuXG4vKiogUmVuZGVycyBhIG5lc3RlZCB2YWx1ZSBhcyBTTkJULCB0aGUgdGV4dCBmb3JtIGEgY29tbWFuZCBhcmd1bWVudCBleHBlY3RzLiAqL1xuY29uc3QgcmVuZGVyU25idCA9ICh2YWx1ZTogdW5rbm93bik6IHN0cmluZyA9PiB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybiAne30nO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSByZXR1cm4gYFwiJHt2YWx1ZS5yZXBsYWNlQWxsKCdcXFxcJywgJ1xcXFxcXFxcJykucmVwbGFjZUFsbCgnXCInLCAnXFxcXFwiJyl9XCJgO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSByZXR1cm4gcmVuZGVyTnVtYmVyKHZhbHVlKTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYmlnaW50JykgcmV0dXJuIGAke3ZhbHVlfUxgO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykgcmV0dXJuIHZhbHVlID8gJzFiJyA6ICcwYic7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSByZXR1cm4gYFske3ZhbHVlLm1hcChyZW5kZXJTbmJ0KS5qb2luKCcsJyl9XWA7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgY29uc3QgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKHZhbHVlKS5tYXAoKFtrZXksIGVudHJ5XSkgPT4gYCR7a2V5fToke3JlbmRlclNuYnQoZW50cnkpfWApO1xuICAgICAgICByZXR1cm4gYHske2VudHJpZXMuam9pbignLCcpfX1gO1xuICAgIH1cbiAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbn07XG4iXSwibWFwcGluZ3MiOiI7OztBQTBCQSxJQUFNLG1CQUFtQjs7Ozs7OztBQVF6QixJQUFNLHNCQUFzQjs7Ozs7Ozs7QUFTNUIsSUFBYSxvQkFBb0IsWUFBeUM7Q0FDdEUsTUFBTSxXQUEyQixDQUFDO0NBQ2xDLE1BQU0sWUFBc0IsQ0FBQztDQUM3QixJQUFJLFVBQVU7Q0FFZCxLQUFLLElBQUksUUFBUSxHQUFHLFFBQVEsUUFBUSxRQUFRLFNBQVMsR0FBRztFQUNwRCxJQUFJLFFBQVEsV0FBVyxPQUFPLFFBQVEsUUFBUSxPQUFPLEtBQUs7R0FDdEQsV0FBVyxRQUFRO0dBQ25CO0VBQ0o7RUFFQSxNQUFNLFFBQVEsUUFBUSxRQUFRLEtBQUssUUFBUSxDQUFDO0VBQzVDLElBQUksVUFB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
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Macro lines and their `$(variable)` substitutions, as 1.20.2 defined them.
3
+ * A macro line is compiled once into a template of literal text and variable
4
+ * holes; a call fills the holes from a compound of arguments and the resulting
5
+ * command is parsed fresh, which is the cost a macro adds over a plain line.
6
+ */
7
+ /** The compound a macro call substitutes from. Extra entries are ignored. */
8
+ export type MacroArguments = Readonly<Record<string, unknown>>;
9
+ /** One piece of a compiled macro line: literal text, or a hole naming a variable. */
10
+ export type MacroSegment = {
11
+ text: string;
12
+ } | {
13
+ variable: string;
14
+ };
15
+ /** A macro line compiled into the pieces a call concatenates. */
16
+ export interface MacroTemplate {
17
+ segments: readonly MacroSegment[];
18
+ /** Every variable the line substitutes, once each, in first-use order. */
19
+ variables: readonly string[];
20
+ }
21
+ /** The outcome of compiling a macro line. */
22
+ export type MacroTemplateResult = {
23
+ ok: true;
24
+ template: MacroTemplate;
25
+ } | {
26
+ ok: false;
27
+ message: string;
28
+ };
29
+ /** The outcome of filling a template from an argument compound. */
30
+ export type MacroSubstitutionResult = {
31
+ ok: true;
32
+ command: string;
33
+ } | {
34
+ ok: false;
35
+ message: string;
36
+ };
37
+ /**
38
+ * Compiles one macro line into a reusable template.
39
+ *
40
+ * `$` is literal unless it is followed by `(`, which is the only escape the
41
+ * format has. A line marked as a macro but carrying no substitution is an
42
+ * error, as is an unterminated `$(` or a name outside letters, digits and `_`.
43
+ */
44
+ export declare const compileMacroLine: (command: string) => MacroTemplateResult;
45
+ /**
46
+ * Fills a compiled macro line from an argument compound.
47
+ *
48
+ * @returns The command to parse, or the reason the call cannot be instantiated.
49
+ */
50
+ export declare const substituteMacro: (template: MacroTemplate, args: MacroArguments) => MacroSubstitutionResult;
51
+ /**
52
+ * Renders one argument the way a substitution inserts it: a string goes in
53
+ * raw, with no quoting and no escaping, so a value carrying quotes can produce
54
+ * a command that no longer parses. Numbers lose the type suffix they would
55
+ * carry in NBT, matching the 1.20.2 fix. A compound or list becomes SNBT,
56
+ * where suffixes are back because the text is NBT again.
57
+ */
58
+ export declare const renderMacroValue: (value: unknown) => string;
59
+ //# sourceMappingURL=macro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macro.d.ts","sourceRoot":"","sources":["../src/macro.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/D,qFAAqF;AACrF,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC1B,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAClC,0EAA0E;IAC1E,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,6CAA6C;AAC7C,MAAM,MAAM,mBAAmB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzG,mEAAmE;AACnE,MAAM,MAAM,uBAAuB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAYrG;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,YAAa,MAAM,KAAG,mBAgClD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,aAAc,aAAa,QAAQ,cAAc,KAAG,uBAiB/E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,UAAW,OAAO,KAAG,MAMjD,CAAC"}
@@ -0,0 +1,115 @@
1
+ // src/macro.ts
2
+ var VARIABLE_PATTERN = /^[A-Za-z0-9_]+$/;
3
+ /**
4
+ * The most fraction digits a non-integer macro argument prints. Java formats
5
+ * the value with a `DecimalFormat` under `Locale.ROOT`; Mojang does not state
6
+ * the digit count, so this is a choice that keeps every double exactly
7
+ * representable in decimal form rather than a confirmed vanilla number.
8
+ */
9
+ var MAX_FRACTION_DIGITS = 17;
10
+ /**
11
+ * Compiles one macro line into a reusable template.
12
+ *
13
+ * `$` is literal unless it is followed by `(`, which is the only escape the
14
+ * format has. A line marked as a macro but carrying no substitution is an
15
+ * error, as is an unterminated `$(` or a name outside letters, digits and `_`.
16
+ */
17
+ var compileMacroLine = (command) => {
18
+ const segments = [];
19
+ const variables = [];
20
+ let literal = "";
21
+ for (let index = 0; index < command.length; index += 1) {
22
+ if (command[index] !== "$" || command[index + 1] !== "(") {
23
+ literal += command[index];
24
+ continue;
25
+ }
26
+ const close = command.indexOf(")", index + 2);
27
+ if (close === -1) return {
28
+ ok: false,
29
+ message: "unterminated macro variable"
30
+ };
31
+ const variable = command.slice(index + 2, close);
32
+ if (!VARIABLE_PATTERN.test(variable)) return {
33
+ ok: false,
34
+ message: `invalid macro variable name '${variable}'`
35
+ };
36
+ if (literal.length > 0) {
37
+ segments.push({ text: literal });
38
+ literal = "";
39
+ }
40
+ segments.push({ variable });
41
+ if (!variables.includes(variable)) variables.push(variable);
42
+ index = close;
43
+ }
44
+ if (variables.length === 0) return {
45
+ ok: false,
46
+ message: "no variables in macro"
47
+ };
48
+ if (literal.length > 0) segments.push({ text: literal });
49
+ return {
50
+ ok: true,
51
+ template: {
52
+ segments,
53
+ variables
54
+ }
55
+ };
56
+ };
57
+ /**
58
+ * Fills a compiled macro line from an argument compound.
59
+ *
60
+ * @returns The command to parse, or the reason the call cannot be instantiated.
61
+ */
62
+ var substituteMacro = (template, args) => {
63
+ let command = "";
64
+ for (const segment of template.segments) {
65
+ if ("text" in segment) {
66
+ command += segment.text;
67
+ continue;
68
+ }
69
+ const value = args[segment.variable];
70
+ if (value === void 0 || value === null) return {
71
+ ok: false,
72
+ message: `the macro arguments have no entry for '${segment.variable}'`
73
+ };
74
+ command += renderMacroValue(value);
75
+ }
76
+ return {
77
+ ok: true,
78
+ command
79
+ };
80
+ };
81
+ /**
82
+ * Renders one argument the way a substitution inserts it: a string goes in
83
+ * raw, with no quoting and no escaping, so a value carrying quotes can produce
84
+ * a command that no longer parses. Numbers lose the type suffix they would
85
+ * carry in NBT, matching the 1.20.2 fix. A compound or list becomes SNBT,
86
+ * where suffixes are back because the text is NBT again.
87
+ */
88
+ var renderMacroValue = (value) => {
89
+ if (typeof value === "string") return value;
90
+ if (typeof value === "number") return renderNumber(value);
91
+ if (typeof value === "bigint") return value.toString();
92
+ if (typeof value === "boolean") return value ? "1" : "0";
93
+ return renderSnbt(value);
94
+ };
95
+ /** Prints a number in plain decimal, never in exponent form and never with a suffix. */
96
+ var renderNumber = (value) => {
97
+ if (!Number.isFinite(value)) return String(value);
98
+ if (Number.isInteger(value) && Math.abs(value) < Number.MAX_SAFE_INTEGER) return value.toFixed(0);
99
+ const fixed = value.toFixed(MAX_FRACTION_DIGITS);
100
+ return fixed.includes(".") ? fixed.replace(/0+$/, "").replace(/\.$/, "") : fixed;
101
+ };
102
+ /** Renders a nested value as SNBT, the text form a command argument expects. */
103
+ var renderSnbt = (value) => {
104
+ if (value === null || value === void 0) return "{}";
105
+ if (typeof value === "string") return `"${value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}"`;
106
+ if (typeof value === "number") return renderNumber(value);
107
+ if (typeof value === "bigint") return `${value}L`;
108
+ if (typeof value === "boolean") return value ? "1b" : "0b";
109
+ if (Array.isArray(value)) return `[${value.map(renderSnbt).join(",")}]`;
110
+ if (typeof value === "object") return `{${Object.entries(value).map(([key, entry]) => `${key}:${renderSnbt(entry)}`).join(",")}}`;
111
+ return String(value);
112
+ };
113
+ export { compileMacroLine, renderMacroValue, substituteMacro };
114
+
115
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFjcm8uZXMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL21hY3JvLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTWFjcm8gbGluZXMgYW5kIHRoZWlyIGAkKHZhcmlhYmxlKWAgc3Vic3RpdHV0aW9ucywgYXMgMS4yMC4yIGRlZmluZWQgdGhlbS5cbiAqIEEgbWFjcm8gbGluZSBpcyBjb21waWxlZCBvbmNlIGludG8gYSB0ZW1wbGF0ZSBvZiBsaXRlcmFsIHRleHQgYW5kIHZhcmlhYmxlXG4gKiBob2xlczsgYSBjYWxsIGZpbGxzIHRoZSBob2xlcyBmcm9tIGEgY29tcG91bmQgb2YgYXJndW1lbnRzIGFuZCB0aGUgcmVzdWx0aW5nXG4gKiBjb21tYW5kIGlzIHBhcnNlZCBmcmVzaCwgd2hpY2ggaXMgdGhlIGNvc3QgYSBtYWNybyBhZGRzIG92ZXIgYSBwbGFpbiBsaW5lLlxuICovXG5cbi8qKiBUaGUgY29tcG91bmQgYSBtYWNybyBjYWxsIHN1YnN0aXR1dGVzIGZyb20uIEV4dHJhIGVudHJpZXMgYXJlIGlnbm9yZWQuICovXG5leHBvcnQgdHlwZSBNYWNyb0FyZ3VtZW50cyA9IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PjtcblxuLyoqIE9uZSBwaWVjZSBvZiBhIGNvbXBpbGVkIG1hY3JvIGxpbmU6IGxpdGVyYWwgdGV4dCwgb3IgYSBob2xlIG5hbWluZyBhIHZhcmlhYmxlLiAqL1xuZXhwb3J0IHR5cGUgTWFjcm9TZWdtZW50ID0geyB0ZXh0OiBzdHJpbmcgfSB8IHsgdmFyaWFibGU6IHN0cmluZyB9O1xuXG4vKiogQSBtYWNybyBsaW5lIGNvbXBpbGVkIGludG8gdGhlIHBpZWNlcyBhIGNhbGwgY29uY2F0ZW5hdGVzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNYWNyb1RlbXBsYXRlIHtcbiAgICBzZWdtZW50czogcmVhZG9ubHkgTWFjcm9TZWdtZW50W107XG4gICAgLyoqIEV2ZXJ5IHZhcmlhYmxlIHRoZSBsaW5lIHN1YnN0aXR1dGVzLCBvbmNlIGVhY2gsIGluIGZpcnN0LXVzZSBvcmRlci4gKi9cbiAgICB2YXJpYWJsZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xufVxuXG4vKiogVGhlIG91dGNvbWUgb2YgY29tcGlsaW5nIGEgbWFjcm8gbGluZS4gKi9cbmV4cG9ydCB0eXBlIE1hY3JvVGVtcGxhdGVSZXN1bHQgPSB7IG9rOiB0cnVlOyB0ZW1wbGF0ZTogTWFjcm9UZW1wbGF0ZSB9IHwgeyBvazogZmFsc2U7IG1lc3NhZ2U6IHN0cmluZyB9O1xuXG4vKiogVGhlIG91dGNvbWUgb2YgZmlsbGluZyBhIHRlbXBsYXRlIGZyb20gYW4gYXJndW1lbnQgY29tcG91bmQuICovXG5leHBvcnQgdHlwZSBNYWNyb1N1YnN0aXR1dGlvblJlc3VsdCA9IHsgb2s6IHRydWU7IGNvbW1hbmQ6IHN0cmluZyB9IHwgeyBvazogZmFsc2U7IG1lc3NhZ2U6IHN0cmluZyB9O1xuXG5jb25zdCBWQVJJQUJMRV9QQVRURVJOID0gL15bQS1aYS16MC05X10rJC87XG5cbi8qKlxuICogVGhlIG1vc3QgZnJhY3Rpb24gZGlnaXRzIGEgbm9uLWludGVnZXIgbWFjcm8gYXJndW1lbnQgcHJpbnRzLiBKYXZhIGZvcm1hdHNcbiAqIHRoZSB2YWx1ZSB3aXRoIGEgYERlY2ltYWxGb3JtYXRgIHVuZGVyIGBMb2NhbGUuUk9PVGA7IE1vamFuZyBkb2VzIG5vdCBzdGF0ZVxuICogdGhlIGRpZ2l0IGNvdW50LCBzbyB0aGlzIGlzIGEgY2hvaWNlIHRoYXQga2VlcHMgZXZlcnkgZG91YmxlIGV4YWN0bHlcbiAqIHJlcHJlc2VudGFibGUgaW4gZGVjaW1hbCBmb3JtIHJhdGhlciB0aGFuIGEgY29uZmlybWVkIHZhbmlsbGEgbnVtYmVyLlxuICovXG5jb25zdCBNQVhfRlJBQ1RJT05fRElHSVRTID0gMTc7XG5cbi8qKlxuICogQ29tcGlsZXMgb25lIG1hY3JvIGxpbmUgaW50byBhIHJldXNhYmxlIHRlbXBsYXRlLlxuICpcbiAqIGAkYCBpcyBsaXRlcmFsIHVubGVzcyBpdCBpcyBmb2xsb3dlZCBieSBgKGAsIHdoaWNoIGlzIHRoZSBvbmx5IGVzY2FwZSB0aGVcbiAqIGZvcm1hdCBoYXMuIEEgbGluZSBtYXJrZWQgYXMgYSBtYWNybyBidXQgY2Fycnlpbmcgbm8gc3Vic3RpdHV0aW9uIGlzIGFuXG4gKiBlcnJvciwgYXMgaXMgYW4gdW50ZXJtaW5hdGVkIGAkKGAgb3IgYSBuYW1lIG91dHNpZGUgbGV0dGVycywgZGlnaXRzIGFuZCBgX2AuXG4gKi9cbmV4cG9ydCBjb25zdCBjb21waWxlTWFjcm9MaW5lID0gKGNvbW1hbmQ6IHN0cmluZyk6IE1hY3JvVGVtcGxhdGVSZXN1bHQgPT4ge1xuICAgIGNvbnN0IHNlZ21lbnRzOiBNYWNyb1NlZ21lbnRbXSA9IFtdO1xuICAgIGNvbnN0IHZhcmlhYmxlczogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgbGl0ZXJhbCA9ICcnO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGNvbW1hbmQubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICAgIGlmIChjb21tYW5kW2luZGV4XSAhPT0gJyQnIHx8IGNvbW1hbmRbaW5kZXggKyAxXSAhPT0gJygnKSB7XG4gICAgICAgICAgICBsaXRlcmFsICs9IGNvbW1hbmRbaW5kZXhdO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbG9zZSA9IGNvbW1hbmQuaW5kZXhPZignKScsIGluZGV4ICsgMik7XG4gICAgICAgIGlmIChjbG9zZSA9PT0gLTEpIHJldHVybiB7IG9rOiBmYWxzZSwgbWVzc2FnZTogJ3VudGVybWluYXRlZCBtYWNybyB2YXJpYWJsZScgfTtcblxuICAgICAgICBjb25zdCB2YXJpYWJsZSA9IGNvbW1hbmQuc2xpY2UoaW5kZXggKyAyLCBjbG9zZSk7XG4gICAgICAgIGlmICghVkFSSUFCTEVfUEFUVEVSTi50ZXN0KHZhcmlhYmxlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBtZXNzYWdlOiBgaW52YWxpZCBtYWNybyB2YXJpYWJsZSBuYW1lICcke3ZhcmlhYmxlfSdgIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGl0ZXJhbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzZWdtZW50cy5wdXNoKHsgdGV4dDogbGl0ZXJhbCB9KTtcbiAgICAgICAgICAgIGxpdGVyYWwgPSAnJztcbiAgICAgICAgfVxuICAgICAgICBzZWdtZW50cy5wdXNoKHsgdmFyaWFibGUgfSk7XG4gICAgICAgIGlmICghdmFyaWFibGVzLmluY2x1ZGVzKHZhcmlhYmxlKSkgdmFyaWFibGVzLnB1c2godmFyaWFibGUpO1xuICAgICAgICBpbmRleCA9IGNsb3NlO1xuICAgIH1cblxuICAgIGlmICh2YXJpYWJsZXMubGVuZ3RoID09PSAwKSByZXR1cm4geyBvazogZmFsc2UsIG1lc3NhZ2U6ICdubyB2YXJpYWJsZXMgaW4gbWFjcm8nIH07XG4gICAgaWYgKGxpdGVyYWwubGVuZ3RoID4gMCkgc2VnbWVudHMucHVzaCh7IHRleHQ6IGxpdGVyYWwgfSk7XG5cbiAgICByZXR1cm4geyBvazogdHJ1ZSwgdGVtcGxhdGU6IHsgc2VnbWVudHMsIHZhcmlhYmxlcyB9IH07XG59O1xuXG4vKipcbiAqIEZpbGxzIGEgY29tcGlsZWQgbWFjcm8gbGluZSBmcm9tIGFuIGFyZ3VtZW50IGNvbXBvdW5kLlxuICpcbiAqIEByZXR1cm5zIFRoZSBjb21tYW5kIHRvIHBhcnNlLCBvciB0aGUgcmVhc29uIHRoZSBjYWxsIGNhbm5vdCBiZSBpbnN0YW50aWF0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBzdWJzdGl0dXRlTWFjcm8gPSAodGVtcGxhdGU6IE1hY3JvVGVtcGxhdGUsIGFyZ3M6IE1hY3JvQXJndW1lbnRzKTogTWFjcm9TdWJzdGl0dXRpb25SZXN1bHQgPT4ge1xuICAgIGxldCBjb21tYW5kID0gJyc7XG5cbiAgICBmb3IgKGNvbnN0IHNlZ21lbnQgb2YgdGVtcGxhdGUuc2VnbWVudHMpIHtcbiAgICAgICAgaWYgKCd0ZXh0JyBpbiBzZWdtZW50KSB7XG4gICAgICAgICAgICBjb21tYW5kICs9IHNlZ21lbnQudGV4dDtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdmFsdWUgPSBhcmdzW3NlZ21lbnQudmFyaWFibGVdO1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBtZXNzYWdlOiBgdGhlIG1hY3JvIGFyZ3VtZW50cyBoYXZlIG5vIGVudHJ5IGZvciAnJHtzZWdtZW50LnZhcmlhYmxlfSdgIH07XG4gICAgICAgIH1cbiAgICAgICAgY29tbWFuZCArPSByZW5kZXJNYWNyb1ZhbHVlKHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBvazogdHJ1ZSwgY29tbWFuZCB9O1xufTtcblxuLyoqXG4gKiBSZW5kZXJzIG9uZSBhcmd1bWVudCB0aGUgd2F5IGEgc3Vic3RpdHV0aW9uIGluc2VydHMgaXQ6IGEgc3RyaW5nIGdvZXMgaW5cbiAqIHJhdywgd2l0aCBubyBxdW90aW5nIGFuZCBubyBlc2NhcGluZywgc28gYSB2YWx1ZSBjYXJyeWluZyBxdW90ZXMgY2FuIHByb2R1Y2VcbiAqIGEgY29tbWFuZCB0aGF0IG5vIGxvbmdlciBwYXJzZXMuIE51bWJlcnMgbG9zZSB0aGUgdHlwZSBzdWZmaXggdGhleSB3b3VsZFxuICogY2FycnkgaW4gTkJULCBtYXRjaGluZyB0aGUgMS4yMC4yIGZpeC4gQSBjb21wb3VuZCBvciBsaXN0IGJlY29tZXMgU05CVCxcbiAqIHdoZXJlIHN1ZmZpeGVzIGFyZSBiYWNrIGJlY2F1c2UgdGhlIHRleHQgaXMgTkJUIGFnYWluLlxuICovXG5leHBvcnQgY29uc3QgcmVuZGVyTWFjcm9WYWx1ZSA9ICh2YWx1ZTogdW5rbm93bik6IHN0cmluZyA9PiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHJldHVybiB2YWx1ZTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykgcmV0dXJuIHJlbmRlck51bWJlcih2YWx1ZSk7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2JpZ2ludCcpIHJldHVybiB2YWx1ZS50b1N0cmluZygpO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykgcmV0dXJuIHZhbHVlID8gJzEnIDogJzAnO1xuICAgIHJldHVybiByZW5kZXJTbmJ0KHZhbHVlKTtcbn07XG5cbi8qKiBQcmludHMgYSBudW1iZXIgaW4gcGxhaW4gZGVjaW1hbCwgbmV2ZXIgaW4gZXhwb25lbnQgZm9ybSBhbmQgbmV2ZXIgd2l0aCBhIHN1ZmZpeC4gKi9cbmNvbnN0IHJlbmRlck51bWJlciA9ICh2YWx1ZTogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZSh2YWx1ZSkpIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSAmJiBNYXRoLmFicyh2YWx1ZSkgPCBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUikgcmV0dXJuIHZhbHVlLnRvRml4ZWQoMCk7XG5cbiAgICBjb25zdCBmaXhlZCA9IHZhbHVlLnRvRml4ZWQoTUFYX0ZSQUNUSU9OX0RJR0lUUyk7XG4gICAgcmV0dXJuIGZpeGVkLmluY2x1ZGVzKCcuJykgPyBmaXhlZC5yZXBsYWNlKC8wKyQvLCAnJykucmVwbGFjZSgvXFwuJC8sICcnKSA6IGZpeGVkO1xufTtcblxuLyoqIFJlbmRlcnMgYSBuZXN0ZWQgdmFsdWUgYXMgU05CVCwgdGhlIHRleHQgZm9ybSBhIGNvbW1hbmQgYXJndW1lbnQgZXhwZWN0cy4gKi9cbmNvbnN0IHJlbmRlclNuYnQgPSAodmFsdWU6IHVua25vd24pOiBzdHJpbmcgPT4ge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gJ3t9JztcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykgcmV0dXJuIGBcIiR7dmFsdWUucmVwbGFjZUFsbCgnXFxcXCcsICdcXFxcXFxcXCcpLnJlcGxhY2VBbGwoJ1wiJywgJ1xcXFxcIicpfVwiYDtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykgcmV0dXJuIHJlbmRlck51bWJlcih2YWx1ZSk7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2JpZ2ludCcpIHJldHVybiBgJHt2YWx1ZX1MYDtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHJldHVybiB2YWx1ZSA/ICcxYicgOiAnMGInO1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuIGBbJHt2YWx1ZS5tYXAocmVuZGVyU25idCkuam9pbignLCcpfV1gO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGNvbnN0IGVudHJpZXMgPSBPYmplY3QuZW50cmllcyh2YWx1ZSkubWFwKChba2V5LCBlbnRyeV0pID0+IGAke2tleX06JHtyZW5kZXJTbmJ0KGVudHJ5KX1gKTtcbiAgICAgICAgcmV0dXJuIGB7JHtlbnRyaWVzLmpvaW4oJywnKX19YDtcbiAgICB9XG4gICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG59O1xuIl0sIm1hcHBpbmdzIjoiO0FBMEJBLElBQU0sbUJBQW1COzs7Ozs7O0FBUXpCLElBQU0sc0JBQXNCOzs7Ozs7OztBQVM1QixJQUFhLG9CQUFvQixZQUF5QztDQUN0RSxNQUFNLFdBQTJCLENBQUM7Q0FDbEMsTUFBTSxZQUFzQixDQUFDO0NBQzdCLElBQUksVUFBVTtDQUVkLEtBQUssSUFBSSxRQUFRLEdBQUcsUUFBUSxRQUFRLFFBQVEsU0FBUyxHQUFHO0VBQ3BELElBQUksUUFBUSxXQUFXLE9BQU8sUUFBUSxRQUFRLE9BQU8sS0FBSztHQUN0RCxXQUFXLFFBQVE7R0FDbkI7RUFDSjtFQUVBLE1BQU0sUUFBUSxRQUFRLFFBQVEsS0FBSyxRQUFRLENBQUM7RUFDNUMsSUFBSSxVQUFVLElB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
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ // src/parse.ts
4
+ /**
5
+ * The longest a single command may be, in characters. Java's
6
+ * `CommandFunction` carries 2000000 as its only integer constant and rejects a
7
+ * longer line with "Command too long".
8
+ */
9
+ var MAX_COMMAND_LENGTH = 2e6;
10
+ /** Whether a line asks for the next line to be appended to it. */
11
+ var continues = (text) => text.endsWith("\\");
12
+ /**
13
+ * Parses the text of one `.mcfunction` file into its command lines.
14
+ *
15
+ * A line is dropped when it is blank or starts with `#`. A line whose last
16
+ * non-whitespace character is `\` continues into the next line, which is
17
+ * trimmed before being appended. A line whose first non-whitespace character
18
+ * is `$` is a macro line and keeps its substitutions unevaluated.
19
+ *
20
+ * Problems are reported rather than thrown; the caller decides whether a
21
+ * function with errors is registered.
22
+ */
23
+ var parseFunctionSource = (source) => {
24
+ const lines = [];
25
+ const diagnostics = [];
26
+ const sourceLines = source.split(/\r?\n/);
27
+ if (sourceLines.at(-1) === "") sourceLines.pop();
28
+ let pending;
29
+ for (const [index, raw] of sourceLines.entries()) {
30
+ const number = index + 1;
31
+ const text = raw.trim();
32
+ if (pending) {
33
+ pending.text += text;
34
+ if (continues(pending.text)) {
35
+ pending.text = pending.text.slice(0, -1);
36
+ continue;
37
+ }
38
+ emit(lines, diagnostics, pending.line, pending.text, pending.macro);
39
+ pending = void 0;
40
+ continue;
41
+ }
42
+ if (text.length === 0 || text.startsWith("#")) continue;
43
+ const macro = text.startsWith("$");
44
+ const command = macro ? text.slice(1).trim() : text;
45
+ if (continues(command)) {
46
+ pending = {
47
+ line: number,
48
+ text: command.slice(0, -1),
49
+ macro
50
+ };
51
+ continue;
52
+ }
53
+ emit(lines, diagnostics, number, command, macro);
54
+ }
55
+ if (pending) diagnostics.push({
56
+ severity: "error",
57
+ code: "line.dangling-continuation",
58
+ line: pending.line,
59
+ message: "the file ends with a line continuation"
60
+ });
61
+ return {
62
+ lines,
63
+ diagnostics
64
+ };
65
+ };
66
+ /** Validates one assembled command and records it, or reports why it was rejected. */
67
+ var emit = (lines, diagnostics, line, command, macro) => {
68
+ if (command.length === 0) return;
69
+ if (command.startsWith("//")) {
70
+ diagnostics.push({
71
+ severity: "error",
72
+ code: "line.double-slash-comment",
73
+ line,
74
+ message: `'${preview(command)}' is not a command; comments use '#', not '//'`
75
+ });
76
+ return;
77
+ }
78
+ if (command.startsWith("/")) {
79
+ diagnostics.push({
80
+ severity: "error",
81
+ code: "line.leading-slash",
82
+ line,
83
+ message: `'${preview(command)}' has a leading slash; function commands are written without one`
84
+ });
85
+ return;
86
+ }
87
+ if (command.length > 2e6) {
88
+ diagnostics.push({
89
+ severity: "error",
90
+ code: "line.too-long",
91
+ line,
92
+ message: `the command is ${command.length} characters, over the ${MAX_COMMAND_LENGTH} character limit`
93
+ });
94
+ return;
95
+ }
96
+ lines.push({
97
+ line,
98
+ command,
99
+ macro
100
+ });
101
+ };
102
+ /** Shortens a command for a diagnostic message. */
103
+ var preview = (command) => command.length <= 40 ? command : `${command.slice(0, 40)}...`;
104
+ exports.MAX_COMMAND_LENGTH = MAX_COMMAND_LENGTH;
105
+ exports.parseFunctionSource = parseFunctionSource;
106
+
107
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UuY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi9zcmMvcGFyc2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgbWNmdW5jdGlvbiBmaWxlIGZvcm1hdDogb25lIGNvbW1hbmQgcGVyIGxpbmUgd2l0aCBubyBsZWFkaW5nIHNsYXNoLFxuICogYCNgIGNvbW1lbnRzLCBibGFuayBsaW5lcywgYFxcYCBsaW5lIGNvbnRpbnVhdGlvbiAoMS4yMC4yKSBhbmQgYCRgIG1hY3JvXG4gKiBsaW5lcyAoMS4yMC4yKS4gUGFyc2luZyBoYXBwZW5zIG9uY2UgcGVyIGZpbGUgYXQgbG9hZCwgd2hpY2ggaXMgdGhlIHBvaW50IG9mXG4gKiB0aGUgZm9ybWF0OiBhIG5vbi1tYWNybyBjb21tYW5kIGxpbmUgaXMgbmV2ZXIgcmUtcmVhZCBhdCBydW4gdGltZS5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IERpYWdub3N0aWMgfSBmcm9tICcuL2RpYWdub3N0aWNzJztcblxuLyoqXG4gKiBUaGUgbG9uZ2VzdCBhIHNpbmdsZSBjb21tYW5kIG1heSBiZSwgaW4gY2hhcmFjdGVycy4gSmF2YSdzXG4gKiBgQ29tbWFuZEZ1bmN0aW9uYCBjYXJyaWVzIDIwMDAwMDAgYXMgaXRzIG9ubHkgaW50ZWdlciBjb25zdGFudCBhbmQgcmVqZWN0cyBhXG4gKiBsb25nZXIgbGluZSB3aXRoIFwiQ29tbWFuZCB0b28gbG9uZ1wiLlxuICovXG5leHBvcnQgY29uc3QgTUFYX0NPTU1BTkRfTEVOR1RIID0gMl8wMDBfMDAwO1xuXG4vKiogT25lIGNvbW1hbmQgdGhlIGZpbGUgZGVjbGFyZXMsIGFmdGVyIGNvbW1lbnRzLCBibGFuayBsaW5lcyBhbmQgY29udGludWF0aW9ucyBhcmUgcmVzb2x2ZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIEZ1bmN0aW9uTGluZSB7XG4gICAgLyoqIFRoZSAxLWJhc2VkIG51bWJlciBvZiB0aGUgbGluZSB0aGUgY29tbWFuZCBzdGFydHMgb24uICovXG4gICAgbGluZTogbnVtYmVyO1xuICAgIC8qKiBUaGUgY29tbWFuZCB0ZXh0LCB3aXRob3V0IHRoZSBsZWFkaW5nIGAkYCBvZiBhIG1hY3JvIGxpbmUuICovXG4gICAgY29tbWFuZDogc3RyaW5nO1xuICAgIC8qKiBXaGV0aGVyIHRoZSBsaW5lIGlzIGEgbWFjcm8gbGluZSwgc28gaXRzIGAkKG5hbWUpYCBzdWJzdGl0dXRpb25zIHJ1biBwZXIgY2FsbC4gKi9cbiAgICBtYWNybzogYm9vbGVhbjtcbn1cblxuLyoqIFdoYXQge0BsaW5rIHBhcnNlRnVuY3Rpb25Tb3VyY2V9IHByb2R1Y2VzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXJzZWRGdW5jdGlvbiB7XG4gICAgbGluZXM6IHJlYWRvbmx5IEZ1bmN0aW9uTGluZVtdO1xuICAgIGRpYWdub3N0aWNzOiByZWFkb25seSBEaWFnbm9zdGljW107XG59XG5cbi8qKiBXaGV0aGVyIGEgbGluZSBhc2tzIGZvciB0aGUgbmV4dCBsaW5lIHRvIGJlIGFwcGVuZGVkIHRvIGl0LiAqL1xuY29uc3QgY29udGludWVzID0gKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4gPT4gdGV4dC5lbmRzV2l0aCgnXFxcXCcpO1xuXG4vKipcbiAqIFBhcnNlcyB0aGUgdGV4dCBvZiBvbmUgYC5tY2Z1bmN0aW9uYCBmaWxlIGludG8gaXRzIGNvbW1hbmQgbGluZXMuXG4gKlxuICogQSBsaW5lIGlzIGRyb3BwZWQgd2hlbiBpdCBpcyBibGFuayBvciBzdGFydHMgd2l0aCBgI2AuIEEgbGluZSB3aG9zZSBsYXN0XG4gKiBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXIgaXMgYFxcYCBjb250aW51ZXMgaW50byB0aGUgbmV4dCBsaW5lLCB3aGljaCBpc1xuICogdHJpbW1lZCBiZWZvcmUgYmVpbmcgYXBwZW5kZWQuIEEgbGluZSB3aG9zZSBmaXJzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXJcbiAqIGlzIGAkYCBpcyBhIG1hY3JvIGxpbmUgYW5kIGtlZXBzIGl0cyBzdWJzdGl0dXRpb25zIHVuZXZhbHVhdGVkLlxuICpcbiAqIFByb2JsZW1zIGFyZSByZXBvcnRlZCByYXRoZXIgdGhhbiB0aHJvd247IHRoZSBjYWxsZXIgZGVjaWRlcyB3aGV0aGVyIGFcbiAqIGZ1bmN0aW9uIHdpdGggZXJyb3JzIGlzIHJlZ2lzdGVyZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBwYXJzZUZ1bmN0aW9uU291cmNlID0gKHNvdXJjZTogc3RyaW5nKTogUGFyc2VkRnVuY3Rpb24gPT4ge1xuICAgIGNvbnN0IGxpbmVzOiBGdW5jdGlvbkxpbmVbXSA9IFtdO1xuICAgIGNvbnN0IGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10gPSBbXTtcbiAgICBjb25zdCBzb3VyY2VMaW5lcyA9IHNvdXJjZS5zcGxpdCgvXFxyP1xcbi8pO1xuICAgIC8vIEEgdHJhaWxpbmcgbmV3bGluZSBpcyBhIHRlcm1pbmF0b3IsIG5vdCBhbiBlbXB0eSBsYXN0IGxpbmUsIHNvIGEgZmlsZSB0aGF0XG4gICAgLy8gZW5kcyBtaWQtY29udGludWF0aW9uIHJlcG9ydHMgdGhlIGNvbnRpbnVhdGlvbiBpbnN0ZWFkIG9mIGNsb3NpbmcgaXQuXG4gICAgaWYgKHNvdXJjZUxpbmVzLmF0KC0xKSA9PT0gJycpIHNvdXJjZUxpbmVzLnBvcCgpO1xuXG4gICAgbGV0IHBlbmRpbmc6IHsgbGluZTogbnVtYmVyOyB0ZXh0OiBzdHJpbmc7IG1hY3JvOiBib29sZWFuIH0gfCB1bmRlZmluZWQ7XG5cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgcmF3XSBvZiBzb3VyY2VMaW5lcy5lbnRyaWVzKCkpIHtcbiAgICAgICAgY29uc3QgbnVtYmVyID0gaW5kZXggKyAxO1xuICAgICAgICBjb25zdCB0ZXh0ID0gcmF3LnRyaW0oKTtcblxuICAgICAgICBpZiAocGVuZGluZykge1xuICAgICAgICAgICAgcGVuZGluZy50ZXh0ICs9IHRleHQ7XG4gICAgICAgICAgICBpZiAoY29udGludWVzKHBlbmRpbmcudGV4dCkpIHtcbiAgICAgICAgICAgICAgICBwZW5kaW5nLnRleHQgPSBwZW5kaW5nLnRleHQuc2xpY2UoMCwgLTEpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW1pdChsaW5lcywgZGlhZ25vc3RpY3MsIHBlbmRpbmcubGluZSwgcGVuZGluZy50ZXh0LCBwZW5kaW5nLm1hY3JvKTtcbiAgICAgICAgICAgIHBlbmRpbmcgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0ZXh0Lmxlbmd0aCA9PT0gMCB8fCB0ZXh0LnN0YXJ0c1dpdGgoJyMnKSkgY29udGludWU7XG5cbiAgICAgICAgY29uc3QgbWFjcm8gPSB0ZXh0LnN0YXJ0c1dpdGgoJyQnKTtcbiAgICAgICAgY29uc3QgY29tbWFuZCA9IG1hY3JvID8gdGV4dC5zbGljZSgxKS50cmltKCkgOiB0ZXh0O1xuXG4gICAgICAgIGlmIChjb250aW51ZXMoY29tbWFuZCkpIHtcbiAgICAgICAgICAgIHBlbmRpbmcgPSB7IGxpbmU6IG51bWJlciwgdGV4dDogY29tbWFuZC5zbGljZSgwLCAtMSksIG1hY3JvIH07XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVtaXQobGluZXMsIGRpYWdub3N0aWNzLCBudW1iZXIsIGNvbW1hbmQsIG1hY3JvKTtcbiAgICB9XG5cbiAgICBpZiAocGVuZGluZykge1xuICAgICAgICBkaWFnbm9zdGljcy5wdXNoKHtcbiAgICAgICAgICAgIHNldmVyaXR5OiAnZXJyb3InLFxuICAgICAgICAgICAgY29kZTogJ2xpbmUuZGFuZ2xpbmctY29udGludWF0aW9uJyxcbiAgICAgICAgICAgIGxpbmU6IHBlbmRpbmcubGluZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6ICd0aGUgZmlsZSBlbmRzIHdpdGggYSBsaW5lIGNvbnRpbnVhdGlvbidcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbGluZXMsIGRpYWdub3N0aWNzIH07XG59O1xuXG4vKiogVmFsaWRhdGVzIG9uZSBhc3NlbWJsZWQgY29tbWFuZCBhbmQgcmVjb3JkcyBpdCwgb3IgcmVwb3J0cyB3aHkgaXQgd2FzIHJlamVjdGVkLiAqL1xuY29uc3QgZW1pdCA9IChcbiAgICBsaW5lczogRnVuY3Rpb25MaW5lW10sXG4gICAgZGlhZ25vc3RpY3M6IERpYWdub3N0aWNbXSxcbiAgICBsaW5lOiBudW1iZXIsXG4gICAgY29tbWFuZDogc3RyaW5nLFxuICAgIG1hY3JvOiBib29sZWFuXG4pOiB2b2lkID0+IHtcbiAgICBpZiAoY29tbWFuZC5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIGlmIChjb21tYW5kLnN0YXJ0c1dpdGgoJy8vJykpIHtcbiAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgIGNvZGU6ICdsaW5lLmRvdWJsZS1zbGFzaC1jb21tZW50JyxcbiAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICBtZXNzYWdlOiBgJyR7cHJldmlldyhjb21tYW5kKX0nIGlzIG5vdCBhIGNvbW1hbmQ7IGNvbW1lbnRzIHVzZSAnIycsIG5vdCAnLy8nYFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjb21tYW5kLnN0YXJ0c1dpdGgoJy8nKSkge1xuICAgICAgICBkaWFnbm9zdGljcy5wdXNoKHtcbiAgICAgICAgICAgIHNldmVyaXR5OiAnZXJyb3InLFxuICAgICAgICAgICAgY29kZTogJ2xpbmUubGVhZGluZy1zbGFzaCcsXG4gICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgbWVzc2FnZTogYCcke3ByZXZpZXcoY29tbWFuZCl9JyBoYXMgYSBsZWFkaW5nIHNsYXNoOyBmdW5jdGlvbiBjb21tYW5kcyBhcmUgd3JpdHRlbiB3aXRob3V0IG9uZWBcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY29tbWFuZC5sZW5ndGggPiBNQVhfQ09NTUFORF9MRU5HVEgpIHtcbiAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgIGNvZGU6ICdsaW5lLnRvby1sb25nJyxcbiAgICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgICBtZXNzYWdlOiBgdGhlIGNvbW1hbmQgaXMgJHtjb21tYW5kLmxlbmd0aH0gY2hhcmFjdGVycywgb3ZlciB0aGUgJHtNQVhfQ09NTUFORF9MRU5HVEh9IGNoYXJhY3RlciBsaW1pdGBcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsaW5lcy5wdXNoKHsgbGluZSwgY29tbWFuZCwgbWFjcm8gfSk7XG59O1xuXG4vKiogU2hvcnRlbnMgYSBjb21tYW5kIGZvciBhIGRpYWdub3N0aWMgbWVzc2FnZS4gKi9cbmNvbnN0IHByZXZpZXcgPSAoY29tbWFuZDogc3RyaW5nKTogc3RyaW5nID0+IChjb21tYW5kLmxlbmd0aCA8PSA0MCA/IGNvbW1hbmQgOiBgJHtjb21tYW5kLnNsaWNlKDAsIDQwKX0uLi5gKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFjQSxJQUFhLHFCQUFxQjs7QUFtQmxDLElBQU0sYUFBYSxTQUEwQixLQUFLLFNBQVMsSUFBSTs7Ozs7Ozs7Ozs7O0FBYS9ELElBQWEsdUJBQXVCLFdBQW1DO0NBQ25FLE1BQU0sUUFBd0IsQ0FBQztDQUMvQixNQUFNLGNBQTRCLENBQUM7Q0FDbkMsTUFBTSxjQUFjLE9BQU8sTUFBTSxPQUFPO0NBR3hDLElBQUksWUFBWSxHQUFHLEVBQUUsTUFBTSxJQUFJLFlBQVksSUFBSTtDQUUvQyxJQUFJO0NBRUosS0FBSyxNQUFNLENBQUMsT0FBTyxRQUFRLFlBQVksUUFBUSxHQUFHO0VBQzlDLE1BQU0sU0FBUyxRQUFRO0VBQ3ZCLE1BQU0sT0FBTyxJQUFJLEtBQUs7RUFFdEIsSUFBSSxTQUFTO0dBQ1QsUUFBUSxRQUFRO0dBQ2hCLElBQUksVUFBVSxRQUFRLElBQUksR0FBRztJQUN6QixRQUFRLE9BQU8sUUFBUSxLQUFLLE1BQU0sR0FBRyxFQUFFO0lBQ3ZDO0dBQ0o7R0FDQSxLQUFLLE9BQU8sYUFBYSxRQUFRLE1BQU0sUUFBUSxNQUFNLFFBQVEsS0FBSztHQUNsRSxVQUFVLEtBQUE7R0FDVjtFQUNKO0VBRUEsSUFBSSxLQUFLLFdBQVcsS0FBSyxLQUFLLFdBQVcsR0FBRyxHQUFHO0VBRS9DLE1BQU0sUUFBUSxLQUFLLFdBQVcsR0FBRztFQUNqQyxNQUFNLFVBQVUsUUFBUSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO0VBRS9DLElBQUksVUFBVSxPQUFPLEdBQUc7R0FDcEIsVUFBVTtJQUFFLE1BQU07SUFBUSxNQUFNLFFBQVEsTUFBTSxHQUFHLEVBQUU7SUFBRztHQUFNO0dBQzVEO0VBQ0o7RUFFQSxLQUFLLE9BQU8sYUFBYSxRQUFRLFNBQVMsS0FBSztDQUNuRDtDQUVBLElBQUksU0FDQSxZQUFZLEtBQUs7RUFDYixVQUFVO0VBQ1YsTUFBTTtFQUNOLE1BQU0sUUFBUTtFQUNkLFNBQVM7Q0FDYixDQUFDO0NBR0wsT0FBTztFQUFFO0VBQU87Q0FBWTtBQUNoQzs7QUFHQSxJQUFNLFFBQ0YsT0FDQSxhQUNBLE1BQ0EsU0FDQSxVQUNPO0NBQ1AsSUFBSSxRQUFRLFdBQVcsR0FBRztDQUUxQixJQUFJLFFBQVEsV0FBVyxJQUFJLEdBQUc7RUFDMUIsWUFBWSxLQUFLO0dBQ2IsVUFBVTtHQUNWLE1BQU07R0FDTjtHQUNBLFNBQVMsSUFBSSxRQUFRLE9BQU8sRUFBRTtFQUNsQyxDQUFDO0VBQ0Q7Q0FDSjtDQUVBLElBQUksUUFBUSxXQUFXLEdBQUcsR0FBRztFQUN6QixZQUFZLEtBQUs7R0FDYixVQUFVO0dBQ1YsTUFBTTtHQUNOO0dBQ0EsU0FBUyxJQUFJLFFBQVEsT0FBTyxFQUFFO0VBQ2xDLENBQUM7RUFDRDtDQUNKO0NBRUEsSUFBSSxRQUFRLFNBQUEsS0FBNkI7RUFDckMsWUFBWSxLQUFLO0dBQ2IsVUFBVTtHQUNWLE1BQU07R0FDTjtHQUNBLFNBQVMsa0JBQWtCLFFBQVEsT0FBTyx3QkFBd0IsbUJBQW1CO0VBQ3pGLENBQUM7RUFDRDtDQUNKO0NBRUEsTUFBTSxLQUFLO0VBQUU7RUFBTTtFQUFTO0NBQU0sQ0FBQztBQUN2Qzs7QUFHQSxJQUFNLFdBQVcsWUFBNkIsUUFBUSxVQUFVLEtBQUssVUFBVSxHQUFHLFFBQVEsTUFBTSxHQUFHLEVBQUUsRUFBRSJ9
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The mcfunction file format: one command per line with no leading slash,
3
+ * `#` comments, blank lines, `\` line continuation (1.20.2) and `$` macro
4
+ * lines (1.20.2). Parsing happens once per file at load, which is the point of
5
+ * the format: a non-macro command line is never re-read at run time.
6
+ */
7
+ import type { Diagnostic } from './diagnostics';
8
+ /**
9
+ * The longest a single command may be, in characters. Java's
10
+ * `CommandFunction` carries 2000000 as its only integer constant and rejects a
11
+ * longer line with "Command too long".
12
+ */
13
+ export declare const MAX_COMMAND_LENGTH = 2000000;
14
+ /** One command the file declares, after comments, blank lines and continuations are resolved. */
15
+ export interface FunctionLine {
16
+ /** The 1-based number of the line the command starts on. */
17
+ line: number;
18
+ /** The command text, without the leading `$` of a macro line. */
19
+ command: string;
20
+ /** Whether the line is a macro line, so its `$(name)` substitutions run per call. */
21
+ macro: boolean;
22
+ }
23
+ /** What {@link parseFunctionSource} produces. */
24
+ export interface ParsedFunction {
25
+ lines: readonly FunctionLine[];
26
+ diagnostics: readonly Diagnostic[];
27
+ }
28
+ /**
29
+ * Parses the text of one `.mcfunction` file into its command lines.
30
+ *
31
+ * A line is dropped when it is blank or starts with `#`. A line whose last
32
+ * non-whitespace character is `\` continues into the next line, which is
33
+ * trimmed before being appended. A line whose first non-whitespace character
34
+ * is `$` is a macro line and keeps its substitutions unevaluated.
35
+ *
36
+ * Problems are reported rather than thrown; the caller decides whether a
37
+ * function with errors is registered.
38
+ */
39
+ export declare const parseFunctionSource: (source: string) => ParsedFunction;
40
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,UAAY,CAAC;AAE5C,iGAAiG;AACjG,MAAM,WAAW,YAAY;IACzB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,KAAK,EAAE,OAAO,CAAC;CAClB;AAED,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;CACtC;AAKD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,WAAY,MAAM,KAAG,cAgDpD,CAAC"}
@@ -0,0 +1,104 @@
1
+ // src/parse.ts
2
+ /**
3
+ * The longest a single command may be, in characters. Java's
4
+ * `CommandFunction` carries 2000000 as its only integer constant and rejects a
5
+ * longer line with "Command too long".
6
+ */
7
+ var MAX_COMMAND_LENGTH = 2e6;
8
+ /** Whether a line asks for the next line to be appended to it. */
9
+ var continues = (text) => text.endsWith("\\");
10
+ /**
11
+ * Parses the text of one `.mcfunction` file into its command lines.
12
+ *
13
+ * A line is dropped when it is blank or starts with `#`. A line whose last
14
+ * non-whitespace character is `\` continues into the next line, which is
15
+ * trimmed before being appended. A line whose first non-whitespace character
16
+ * is `$` is a macro line and keeps its substitutions unevaluated.
17
+ *
18
+ * Problems are reported rather than thrown; the caller decides whether a
19
+ * function with errors is registered.
20
+ */
21
+ var parseFunctionSource = (source) => {
22
+ const lines = [];
23
+ const diagnostics = [];
24
+ const sourceLines = source.split(/\r?\n/);
25
+ if (sourceLines.at(-1) === "") sourceLines.pop();
26
+ let pending;
27
+ for (const [index, raw] of sourceLines.entries()) {
28
+ const number = index + 1;
29
+ const text = raw.trim();
30
+ if (pending) {
31
+ pending.text += text;
32
+ if (continues(pending.text)) {
33
+ pending.text = pending.text.slice(0, -1);
34
+ continue;
35
+ }
36
+ emit(lines, diagnostics, pending.line, pending.text, pending.macro);
37
+ pending = void 0;
38
+ continue;
39
+ }
40
+ if (text.length === 0 || text.startsWith("#")) continue;
41
+ const macro = text.startsWith("$");
42
+ const command = macro ? text.slice(1).trim() : text;
43
+ if (continues(command)) {
44
+ pending = {
45
+ line: number,
46
+ text: command.slice(0, -1),
47
+ macro
48
+ };
49
+ continue;
50
+ }
51
+ emit(lines, diagnostics, number, command, macro);
52
+ }
53
+ if (pending) diagnostics.push({
54
+ severity: "error",
55
+ code: "line.dangling-continuation",
56
+ line: pending.line,
57
+ message: "the file ends with a line continuation"
58
+ });
59
+ return {
60
+ lines,
61
+ diagnostics
62
+ };
63
+ };
64
+ /** Validates one assembled command and records it, or reports why it was rejected. */
65
+ var emit = (lines, diagnostics, line, command, macro) => {
66
+ if (command.length === 0) return;
67
+ if (command.startsWith("//")) {
68
+ diagnostics.push({
69
+ severity: "error",
70
+ code: "line.double-slash-comment",
71
+ line,
72
+ message: `'${preview(command)}' is not a command; comments use '#', not '//'`
73
+ });
74
+ return;
75
+ }
76
+ if (command.startsWith("/")) {
77
+ diagnostics.push({
78
+ severity: "error",
79
+ code: "line.leading-slash",
80
+ line,
81
+ message: `'${preview(command)}' has a leading slash; function commands are written without one`
82
+ });
83
+ return;
84
+ }
85
+ if (command.length > 2e6) {
86
+ diagnostics.push({
87
+ severity: "error",
88
+ code: "line.too-long",
89
+ line,
90
+ message: `the command is ${command.length} characters, over the ${MAX_COMMAND_LENGTH} character limit`
91
+ });
92
+ return;
93
+ }
94
+ lines.push({
95
+ line,
96
+ command,
97
+ macro
98
+ });
99
+ };
100
+ /** Shortens a command for a diagnostic message. */
101
+ var preview = (command) => command.length <= 40 ? command : `${command.slice(0, 40)}...`;
102
+ export { MAX_COMMAND_LENGTH, parseFunctionSource };
103
+
104
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UuZXMuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL3BhcnNlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIG1jZnVuY3Rpb24gZmlsZSBmb3JtYXQ6IG9uZSBjb21tYW5kIHBlciBsaW5lIHdpdGggbm8gbGVhZGluZyBzbGFzaCxcbiAqIGAjYCBjb21tZW50cywgYmxhbmsgbGluZXMsIGBcXGAgbGluZSBjb250aW51YXRpb24gKDEuMjAuMikgYW5kIGAkYCBtYWNyb1xuICogbGluZXMgKDEuMjAuMikuIFBhcnNpbmcgaGFwcGVucyBvbmNlIHBlciBmaWxlIGF0IGxvYWQsIHdoaWNoIGlzIHRoZSBwb2ludCBvZlxuICogdGhlIGZvcm1hdDogYSBub24tbWFjcm8gY29tbWFuZCBsaW5lIGlzIG5ldmVyIHJlLXJlYWQgYXQgcnVuIHRpbWUuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBEaWFnbm9zdGljIH0gZnJvbSAnLi9kaWFnbm9zdGljcyc7XG5cbi8qKlxuICogVGhlIGxvbmdlc3QgYSBzaW5nbGUgY29tbWFuZCBtYXkgYmUsIGluIGNoYXJhY3RlcnMuIEphdmEnc1xuICogYENvbW1hbmRGdW5jdGlvbmAgY2FycmllcyAyMDAwMDAwIGFzIGl0cyBvbmx5IGludGVnZXIgY29uc3RhbnQgYW5kIHJlamVjdHMgYVxuICogbG9uZ2VyIGxpbmUgd2l0aCBcIkNvbW1hbmQgdG9vIGxvbmdcIi5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9DT01NQU5EX0xFTkdUSCA9IDJfMDAwXzAwMDtcblxuLyoqIE9uZSBjb21tYW5kIHRoZSBmaWxlIGRlY2xhcmVzLCBhZnRlciBjb21tZW50cywgYmxhbmsgbGluZXMgYW5kIGNvbnRpbnVhdGlvbnMgYXJlIHJlc29sdmVkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBGdW5jdGlvbkxpbmUge1xuICAgIC8qKiBUaGUgMS1iYXNlZCBudW1iZXIgb2YgdGhlIGxpbmUgdGhlIGNvbW1hbmQgc3RhcnRzIG9uLiAqL1xuICAgIGxpbmU6IG51bWJlcjtcbiAgICAvKiogVGhlIGNvbW1hbmQgdGV4dCwgd2l0aG91dCB0aGUgbGVhZGluZyBgJGAgb2YgYSBtYWNybyBsaW5lLiAqL1xuICAgIGNvbW1hbmQ6IHN0cmluZztcbiAgICAvKiogV2hldGhlciB0aGUgbGluZSBpcyBhIG1hY3JvIGxpbmUsIHNvIGl0cyBgJChuYW1lKWAgc3Vic3RpdHV0aW9ucyBydW4gcGVyIGNhbGwuICovXG4gICAgbWFjcm86IGJvb2xlYW47XG59XG5cbi8qKiBXaGF0IHtAbGluayBwYXJzZUZ1bmN0aW9uU291cmNlfSBwcm9kdWNlcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkRnVuY3Rpb24ge1xuICAgIGxpbmVzOiByZWFkb25seSBGdW5jdGlvbkxpbmVbXTtcbiAgICBkaWFnbm9zdGljczogcmVhZG9ubHkgRGlhZ25vc3RpY1tdO1xufVxuXG4vKiogV2hldGhlciBhIGxpbmUgYXNrcyBmb3IgdGhlIG5leHQgbGluZSB0byBiZSBhcHBlbmRlZCB0byBpdC4gKi9cbmNvbnN0IGNvbnRpbnVlcyA9ICh0ZXh0OiBzdHJpbmcpOiBib29sZWFuID0+IHRleHQuZW5kc1dpdGgoJ1xcXFwnKTtcblxuLyoqXG4gKiBQYXJzZXMgdGhlIHRleHQgb2Ygb25lIGAubWNmdW5jdGlvbmAgZmlsZSBpbnRvIGl0cyBjb21tYW5kIGxpbmVzLlxuICpcbiAqIEEgbGluZSBpcyBkcm9wcGVkIHdoZW4gaXQgaXMgYmxhbmsgb3Igc3RhcnRzIHdpdGggYCNgLiBBIGxpbmUgd2hvc2UgbGFzdFxuICogbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVyIGlzIGBcXGAgY29udGludWVzIGludG8gdGhlIG5leHQgbGluZSwgd2hpY2ggaXNcbiAqIHRyaW1tZWQgYmVmb3JlIGJlaW5nIGFwcGVuZGVkLiBBIGxpbmUgd2hvc2UgZmlyc3Qgbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVyXG4gKiBpcyBgJGAgaXMgYSBtYWNybyBsaW5lIGFuZCBrZWVwcyBpdHMgc3Vic3RpdHV0aW9ucyB1bmV2YWx1YXRlZC5cbiAqXG4gKiBQcm9ibGVtcyBhcmUgcmVwb3J0ZWQgcmF0aGVyIHRoYW4gdGhyb3duOyB0aGUgY2FsbGVyIGRlY2lkZXMgd2hldGhlciBhXG4gKiBmdW5jdGlvbiB3aXRoIGVycm9ycyBpcyByZWdpc3RlcmVkLlxuICovXG5leHBvcnQgY29uc3QgcGFyc2VGdW5jdGlvblNvdXJjZSA9IChzb3VyY2U6IHN0cmluZyk6IFBhcnNlZEZ1bmN0aW9uID0+IHtcbiAgICBjb25zdCBsaW5lczogRnVuY3Rpb25MaW5lW10gPSBbXTtcbiAgICBjb25zdCBkaWFnbm9zdGljczogRGlhZ25vc3RpY1tdID0gW107XG4gICAgY29uc3Qgc291cmNlTGluZXMgPSBzb3VyY2Uuc3BsaXQoL1xccj9cXG4vKTtcbiAgICAvLyBBIHRyYWlsaW5nIG5ld2xpbmUgaXMgYSB0ZXJtaW5hdG9yLCBub3QgYW4gZW1wdHkgbGFzdCBsaW5lLCBzbyBhIGZpbGUgdGhhdFxuICAgIC8vIGVuZHMgbWlkLWNvbnRpbnVhdGlvbiByZXBvcnRzIHRoZSBjb250aW51YXRpb24gaW5zdGVhZCBvZiBjbG9zaW5nIGl0LlxuICAgIGlmIChzb3VyY2VMaW5lcy5hdCgtMSkgPT09ICcnKSBzb3VyY2VMaW5lcy5wb3AoKTtcblxuICAgIGxldCBwZW5kaW5nOiB7IGxpbmU6IG51bWJlcjsgdGV4dDogc3RyaW5nOyBtYWNybzogYm9vbGVhbiB9IHwgdW5kZWZpbmVkO1xuXG4gICAgZm9yIChjb25zdCBbaW5kZXgsIHJhd10gb2Ygc291cmNlTGluZXMuZW50cmllcygpKSB7XG4gICAgICAgIGNvbnN0IG51bWJlciA9IGluZGV4ICsgMTtcbiAgICAgICAgY29uc3QgdGV4dCA9IHJhdy50cmltKCk7XG5cbiAgICAgICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgICAgICAgIHBlbmRpbmcudGV4dCArPSB0ZXh0O1xuICAgICAgICAgICAgaWYgKGNvbnRpbnVlcyhwZW5kaW5nLnRleHQpKSB7XG4gICAgICAgICAgICAgICAgcGVuZGluZy50ZXh0ID0gcGVuZGluZy50ZXh0LnNsaWNlKDAsIC0xKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVtaXQobGluZXMsIGRpYWdub3N0aWNzLCBwZW5kaW5nLmxpbmUsIHBlbmRpbmcudGV4dCwgcGVuZGluZy5tYWNybyk7XG4gICAgICAgICAgICBwZW5kaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGV4dC5sZW5ndGggPT09IDAgfHwgdGV4dC5zdGFydHNXaXRoKCcjJykpIGNvbnRpbnVlO1xuXG4gICAgICAgIGNvbnN0IG1hY3JvID0gdGV4dC5zdGFydHNXaXRoKCckJyk7XG4gICAgICAgIGNvbnN0IGNvbW1hbmQgPSBtYWNybyA/IHRleHQuc2xpY2UoMSkudHJpbSgpIDogdGV4dDtcblxuICAgICAgICBpZiAoY29udGludWVzKGNvbW1hbmQpKSB7XG4gICAgICAgICAgICBwZW5kaW5nID0geyBsaW5lOiBudW1iZXIsIHRleHQ6IGNvbW1hbmQuc2xpY2UoMCwgLTEpLCBtYWNybyB9O1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBlbWl0KGxpbmVzLCBkaWFnbm9zdGljcywgbnVtYmVyLCBjb21tYW5kLCBtYWNybyk7XG4gICAgfVxuXG4gICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgIGNvZGU6ICdsaW5lLmRhbmdsaW5nLWNvbnRpbnVhdGlvbicsXG4gICAgICAgICAgICBsaW5lOiBwZW5kaW5nLmxpbmUsXG4gICAgICAgICAgICBtZXNzYWdlOiAndGhlIGZpbGUgZW5kcyB3aXRoIGEgbGluZSBjb250aW51YXRpb24nXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7IGxpbmVzLCBkaWFnbm9zdGljcyB9O1xufTtcblxuLyoqIFZhbGlkYXRlcyBvbmUgYXNzZW1ibGVkIGNvbW1hbmQgYW5kIHJlY29yZHMgaXQsIG9yIHJlcG9ydHMgd2h5IGl0IHdhcyByZWplY3RlZC4gKi9cbmNvbnN0IGVtaXQgPSAoXG4gICAgbGluZXM6IEZ1bmN0aW9uTGluZVtdLFxuICAgIGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10sXG4gICAgbGluZTogbnVtYmVyLFxuICAgIGNvbW1hbmQ6IHN0cmluZyxcbiAgICBtYWNybzogYm9vbGVhblxuKTogdm9pZCA9PiB7XG4gICAgaWYgKGNvbW1hbmQubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICBpZiAoY29tbWFuZC5zdGFydHNXaXRoKCcvLycpKSB7XG4gICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgc2V2ZXJpdHk6ICdlcnJvcicsXG4gICAgICAgICAgICBjb2RlOiAnbGluZS5kb3VibGUtc2xhc2gtY29tbWVudCcsXG4gICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgbWVzc2FnZTogYCcke3ByZXZpZXcoY29tbWFuZCl9JyBpcyBub3QgYSBjb21tYW5kOyBjb21tZW50cyB1c2UgJyMnLCBub3QgJy8vJ2BcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY29tbWFuZC5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgICAgZGlhZ25vc3RpY3MucHVzaCh7XG4gICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgIGNvZGU6ICdsaW5lLmxlYWRpbmctc2xhc2gnLFxuICAgICAgICAgICAgbGluZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGAnJHtwcmV2aWV3KGNvbW1hbmQpfScgaGFzIGEgbGVhZGluZyBzbGFzaDsgZnVuY3Rpb24gY29tbWFuZHMgYXJlIHdyaXR0ZW4gd2l0aG91dCBvbmVgXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbW1hbmQubGVuZ3RoID4gTUFYX0NPTU1BTkRfTEVOR1RIKSB7XG4gICAgICAgIGRpYWdub3N0aWNzLnB1c2goe1xuICAgICAgICAgICAgc2V2ZXJpdHk6ICdlcnJvcicsXG4gICAgICAgICAgICBjb2RlOiAnbGluZS50b28tbG9uZycsXG4gICAgICAgICAgICBsaW5lLFxuICAgICAgICAgICAgbWVzc2FnZTogYHRoZSBjb21tYW5kIGlzICR7Y29tbWFuZC5sZW5ndGh9IGNoYXJhY3RlcnMsIG92ZXIgdGhlICR7TUFYX0NPTU1BTkRfTEVOR1RIfSBjaGFyYWN0ZXIgbGltaXRgXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGluZXMucHVzaCh7IGxpbmUsIGNvbW1hbmQsIG1hY3JvIH0pO1xufTtcblxuLyoqIFNob3J0ZW5zIGEgY29tbWFuZCBmb3IgYSBkaWFnbm9zdGljIG1lc3NhZ2UuICovXG5jb25zdCBwcmV2aWV3ID0gKGNvbW1hbmQ6IHN0cmluZyk6IHN0cmluZyA9PiAoY29tbWFuZC5sZW5ndGggPD0gNDAgPyBjb21tYW5kIDogYCR7Y29tbWFuZC5zbGljZSgwLCA0MCl9Li4uYCk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQWNBLElBQWEscUJBQXFCOztBQW1CbEMsSUFBTSxhQUFhLFNBQTBCLEtBQUssU0FBUyxJQUFJOzs7Ozs7Ozs7Ozs7QUFhL0QsSUFBYSx1QkFBdUIsV0FBbUM7Q0FDbkUsTUFBTSxRQUF3QixDQUFDO0NBQy9CLE1BQU0sY0FBNEIsQ0FBQztDQUNuQyxNQUFNLGNBQWMsT0FBTyxNQUFNLE9BQU87Q0FHeEMsSUFBSSxZQUFZLEdBQUcsRUFBRSxNQUFNLElBQUksWUFBWSxJQUFJO0NBRS9DLElBQUk7Q0FFSixLQUFLLE1BQU0sQ0FBQyxPQUFPLFFBQVEsWUFBWSxRQUFRLEdBQUc7RUFDOUMsTUFBTSxTQUFTLFFBQVE7RUFDdkIsTUFBTSxPQUFPLElBQUksS0FBSztFQUV0QixJQUFJLFNBQVM7R0FDVCxRQUFRLFFBQVE7R0FDaEIsSUFBSSxVQUFVLFFBQVEsSUFBSSxHQUFHO0lBQ3pCLFFBQVEsT0FBTyxRQUFRLEtBQUssTUFBTSxHQUFHLEVBQUU7SUFDdkM7R0FDSjtHQUNBLEtBQUssT0FBTyxhQUFhLFFBQVEsTUFBTSxRQUFRLE1BQU0sUUFBUSxLQUFLO0dBQ2xFLFVBQVUsS0FBQTtHQUNWO0VBQ0o7RUFFQSxJQUFJLEtBQUssV0FBVyxLQUFLLEtBQUssV0FBVyxHQUFHLEdBQUc7RUFFL0MsTUFBTSxRQUFRLEtBQUssV0FBVyxHQUFHO0VBQ2pDLE1BQU0sVUFBVSxRQUFRLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUk7RUFFL0MsSUFBSSxVQUFVLE9BQU8sR0FBRztHQUNwQixVQUFVO0lBQUUsTUFBTTtJQUFRLE1BQU0sUUFBUSxNQUFNLEdBQUcsRUFBRTtJQUFHO0dBQU07R0FDNUQ7RUFDSjtFQUVBLEtBQUssT0FBTyxhQUFhLFFBQVEsU0FBUyxLQUFLO0NBQ25EO0NBRUEsSUFBSSxTQUNBLFlBQVksS0FBSztFQUNiLFVBQVU7RUFDVixNQUFNO0VBQ04sTUFBTSxRQUFRO0VBQ2QsU0FBUztDQUNiLENBQUM7Q0FHTCxPQUFPO0VBQUU7RUFBTztDQUFZO0FBQ2hDOztBQUdBLElBQU0sUUFDRixPQUNBLGFBQ0EsTUFDQSxTQUNBLFVBQ087Q0FDUCxJQUFJLFFBQVEsV0FBVyxHQUFHO0NBRTFCLElBQUksUUFBUSxXQUFXLElBQUksR0FBRztFQUMxQixZQUFZLEtBQUs7R0FDYixVQUFVO0dBQ1YsTUFBTTtHQUNOO0dBQ0EsU0FBUyxJQUFJLFFBQVEsT0FBTyxFQUFFO0VBQ2xDLENBQUM7RUFDRDtDQUNKO0NBRUEsSUFBSSxRQUFRLFdBQVcsR0FBRyxHQUFHO0VBQ3pCLFlBQVksS0FBSztHQUNiLFVBQVU7R0FDVixNQUFNO0dBQ047R0FDQSxTQUFTLElBQUksUUFBUSxPQUFPLEVBQUU7RUFDbEMsQ0FBQztFQUNEO0NBQ0o7Q0FFQSxJQUFJLFFBQVEsU0FBQSxLQUE2QjtFQUNyQyxZQUFZLEtBQUs7R0FDYixVQUFVO0dBQ1YsTUFBTTtHQUNOO0dBQ0EsU0FBUyxrQkFBa0IsUUFBUSxPQUFPLHdCQUF3QixtQkFBbUI7RUFDekYsQ0FBQztFQUNEO0NBQ0o7Q0FFQSxNQUFNLEtBQUs7RUFBRTtFQUFNO0VBQVM7Q0FBTSxDQUFDO0FBQ3ZDOztBQUdBLElBQU0sV0FBVyxZQUE2QixRQUFRLFVBQVUsS0FBSyxVQUFVLEdBQUcsUUFBUSxNQUFNLEdBQUcsRUFBRSxFQUFFIn0=