poe-svelte-ui-lib 1.74.0 → 1.74.1
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.
|
@@ -19,7 +19,7 @@ const encodeUInt = (input) => {
|
|
|
19
19
|
if (value <= 0xffffn)
|
|
20
20
|
return [0x19, Number(value >> 8n), Number(value & 0xffn)];
|
|
21
21
|
if (value <= 0xffffffffn)
|
|
22
|
-
return [0x1a, Number(value >> 24n), Number(value >> 16n & 0xffn), Number(value >> 8n & 0xffn), Number(value & 0xffn)];
|
|
22
|
+
return [0x1a, Number(value >> 24n), Number((value >> 16n) & 0xffn), Number((value >> 8n) & 0xffn), Number(value & 0xffn)];
|
|
23
23
|
throw new Error("xPOE-Debug integer is out of range");
|
|
24
24
|
};
|
|
25
25
|
export const xPoeDebugCmd = (header, argument) => {
|
|
@@ -41,8 +41,13 @@ export const encodeXPoeDebugFrame = (header, argument, value, srcId = 0, freeHea
|
|
|
41
41
|
const crc = crc16Kermit(0, prefix);
|
|
42
42
|
return new Uint8Array([...prefix, ...encodeUInt(crc)]);
|
|
43
43
|
};
|
|
44
|
-
const textItems = (bytes) => decoder
|
|
45
|
-
|
|
44
|
+
const textItems = (bytes) => decoder
|
|
45
|
+
.decode(bytes)
|
|
46
|
+
.split("\n")
|
|
47
|
+
.map((line) => line.trim())
|
|
48
|
+
.filter((line) => line && ![...line].some((char) => char.charCodeAt(0) < 0x20 && char !== "\t"))
|
|
49
|
+
.map((text) => ({ type: "raw", text }));
|
|
50
|
+
const readUInt = (value) => (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 0xffff ? value : null);
|
|
46
51
|
/* Декодирует одну definite array из начала буфера; null означает неполный или невалидный кадр. */
|
|
47
52
|
const frameItem = (buffer) => {
|
|
48
53
|
if (buffer[0] !== ARRAY5)
|
|
@@ -63,14 +68,27 @@ const frameItem = (buffer) => {
|
|
|
63
68
|
const freeHeapValue = fields.decode();
|
|
64
69
|
const crcStart = 1 + fields.offset;
|
|
65
70
|
const crc = readUInt(fields.decode());
|
|
66
|
-
if (fields.offset !== length - 1 ||
|
|
71
|
+
if (fields.offset !== length - 1 ||
|
|
72
|
+
crc === null ||
|
|
73
|
+
(freeHeapValue !== null && (typeof freeHeapValue !== "number" || !Number.isInteger(freeHeapValue) || freeHeapValue < 0)))
|
|
67
74
|
return { status: "garbage" };
|
|
68
75
|
const valueBytes = buffer.slice(valueStart, valueEnd);
|
|
69
76
|
const { header, argument } = splitCmd(cmd);
|
|
70
77
|
return {
|
|
71
78
|
status: "complete",
|
|
72
79
|
length,
|
|
73
|
-
item: {
|
|
80
|
+
item: {
|
|
81
|
+
type: "frame",
|
|
82
|
+
srcId,
|
|
83
|
+
cmd,
|
|
84
|
+
header: Object.entries(HEADER_CODES).find(([, code]) => code === header)?.[0] ?? String(header),
|
|
85
|
+
argument: nameByCode(DEFAULT_ARGUMENT_CODES, argument),
|
|
86
|
+
value: Array.from(valueBytes, (byte) => byte.toString(16).padStart(2, "0").toUpperCase()).join(""),
|
|
87
|
+
valueBytes,
|
|
88
|
+
crc: crc.toString(16).toUpperCase().padStart(4, "0"),
|
|
89
|
+
crcOk: crc16Kermit(0, buffer.subarray(0, crcStart)) === crc,
|
|
90
|
+
freeHeap: typeof freeHeapValue === "number" ? String(freeHeapValue) : "",
|
|
91
|
+
},
|
|
74
92
|
};
|
|
75
93
|
}
|
|
76
94
|
catch (error) {
|
|
@@ -124,7 +142,9 @@ export const createXPoeDebugParser = () => {
|
|
|
124
142
|
}
|
|
125
143
|
return items;
|
|
126
144
|
},
|
|
127
|
-
reset() {
|
|
145
|
+
reset() {
|
|
146
|
+
buffer = new Uint8Array();
|
|
147
|
+
},
|
|
128
148
|
};
|
|
129
149
|
};
|
|
130
150
|
/* Value form input: ready CBOR hex passes through; JSON is converted to CBOR. */
|
|
@@ -52,6 +52,17 @@ export function formatXPoeDebugValueForTable(rawValue, isCbor = true) {
|
|
|
52
52
|
const COPY_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" aria-hidden="true"><g fill="none" stroke="currentColor" stroke-width="1.5"><path d="M6 11c0-2.828 0-4.243.879-5.121C7.757 5 9.172 5 12 5h3c2.828 0 4.243 0 5.121.879C21 6.757 21 8.172 21 11v5c0 2.828 0 4.243-.879 5.121C19.243 22 17.828 22 15 22h-3c-2.828 0-4.243 0-5.121-.879C6 20.243 6 18.828 6 16z"/><path d="M6 19a3 3 0 0 1-3-3v-6c0-3.771 0-5.657 1.172-6.828S7.229 2 11 2h4a3 3 0 0 1 3 3"/></g></svg>`;
|
|
53
53
|
const COPIED_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" aria-hidden="true"><path d="m5 12 4 4L19 6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
54
54
|
let copyBindings = 0;
|
|
55
|
+
let copyObserver = null;
|
|
56
|
+
const removeXPoeDebugModalFooters = () => {
|
|
57
|
+
document.querySelectorAll("[data-modal]").forEach((modal) => {
|
|
58
|
+
if (!modal.querySelector("[data-xpoe-debug-modal]"))
|
|
59
|
+
return;
|
|
60
|
+
const footer = modal.lastElementChild;
|
|
61
|
+
if (!footer || modal.children.length < 3)
|
|
62
|
+
return;
|
|
63
|
+
footer.remove();
|
|
64
|
+
});
|
|
65
|
+
};
|
|
55
66
|
const handleCopyClick = (event) => {
|
|
56
67
|
if (!(event.target instanceof Element))
|
|
57
68
|
return;
|
|
@@ -79,15 +90,22 @@ const handleCopyClick = (event) => {
|
|
|
79
90
|
};
|
|
80
91
|
/* Делегированный обработчик кнопок модального окна; возвращённую функцию вызывают при уничтожении страницы. */
|
|
81
92
|
export function bindXPoeDebugCopyButtons() {
|
|
82
|
-
if (copyBindings++ === 0)
|
|
93
|
+
if (copyBindings++ === 0) {
|
|
83
94
|
document.addEventListener("click", handleCopyClick);
|
|
95
|
+
removeXPoeDebugModalFooters();
|
|
96
|
+
copyObserver = new MutationObserver(removeXPoeDebugModalFooters);
|
|
97
|
+
copyObserver.observe(document.documentElement, { childList: true, subtree: true });
|
|
98
|
+
}
|
|
84
99
|
let isBound = true;
|
|
85
100
|
return () => {
|
|
86
101
|
if (!isBound)
|
|
87
102
|
return;
|
|
88
103
|
isBound = false;
|
|
89
|
-
if (--copyBindings === 0)
|
|
104
|
+
if (--copyBindings === 0) {
|
|
90
105
|
document.removeEventListener("click", handleCopyClick);
|
|
106
|
+
copyObserver?.disconnect();
|
|
107
|
+
copyObserver = null;
|
|
108
|
+
}
|
|
91
109
|
};
|
|
92
110
|
}
|
|
93
111
|
/* Две прокручиваемые секции модалки; HEX-раздел появляется, если форматтер таблицы добавил исходные байты. */
|
|
@@ -103,5 +121,5 @@ export function formatXPoeDebugModal(text) {
|
|
|
103
121
|
const buttonClass = "flex size-7 cursor-pointer items-center justify-center rounded-lg border-none bg-transparent text-(--faint-color) transition-colors duration-150 hover:bg-(--container-color) hover:text-(--font-color)";
|
|
104
122
|
const textStyle = "display:block;min-width:0;max-width:100%;margin:0;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;font:inherit";
|
|
105
123
|
const pane = (title, target, value) => `<section style="${sectionStyle}"><div style="${headingStyle}"><span>${title}</span><button type="button" class="${buttonClass}" data-xpoe-copy="${target}" aria-label="Копировать ${title}" style="${buttonStyle}">${COPY_ICON}</button></div><pre style="${textStyle}">${value}</pre></section>`;
|
|
106
|
-
return `<
|
|
124
|
+
return `<div data-xpoe-debug-modal style="${modalStyle}">${pane("Value", "value", decoded)}${hexIndex < 0 ? "" : pane("HEX", "hex", hex)}</div>`;
|
|
107
125
|
}
|