Phase 2/4 done, working on phase 3/5
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import type { Interface, Widget, SignalRef } from './types';
|
||||
|
||||
/**
|
||||
* Parse an interface XML string into an Interface object.
|
||||
*
|
||||
* Expected XML format:
|
||||
* <interface name="..." version="1">
|
||||
* <widget id="w1" type="textview" x="100" y="50" w="200" h="60">
|
||||
* <signal ds="stub" name="sine_1hz" color="#ff0000"/>
|
||||
* <option key="label" value="Sine 1Hz"/>
|
||||
* </widget>
|
||||
* </interface>
|
||||
*/
|
||||
export function parseInterface(xml: string): Interface {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(xml, 'application/xml');
|
||||
|
||||
// Check for parse errors
|
||||
const parseError = doc.querySelector('parsererror');
|
||||
if (parseError) {
|
||||
throw new Error(`XML parse error: ${parseError.textContent}`);
|
||||
}
|
||||
|
||||
const root = doc.documentElement;
|
||||
if (root.tagName !== 'interface') {
|
||||
throw new Error(`Expected root element <interface>, got <${root.tagName}>`);
|
||||
}
|
||||
|
||||
const name = root.getAttribute('name') ?? 'Untitled';
|
||||
const version = parseInt(root.getAttribute('version') ?? '1', 10);
|
||||
|
||||
const widgets: Widget[] = [];
|
||||
|
||||
for (const el of Array.from(root.children)) {
|
||||
if (el.tagName !== 'widget') continue;
|
||||
|
||||
const id = el.getAttribute('id') ?? '';
|
||||
const type = el.getAttribute('type') ?? 'unknown';
|
||||
const x = parseFloat(el.getAttribute('x') ?? '0');
|
||||
const y = parseFloat(el.getAttribute('y') ?? '0');
|
||||
const w = parseFloat(el.getAttribute('w') ?? '100');
|
||||
const h = parseFloat(el.getAttribute('h') ?? '60');
|
||||
|
||||
const signals: Array<SignalRef & { color?: string }> = [];
|
||||
const options: Record<string, string> = {};
|
||||
|
||||
for (const child of Array.from(el.children)) {
|
||||
if (child.tagName === 'signal') {
|
||||
const ds = child.getAttribute('ds') ?? '';
|
||||
const sigName = child.getAttribute('name') ?? '';
|
||||
const color = child.getAttribute('color') ?? undefined;
|
||||
signals.push({ ds, name: sigName, ...(color ? { color } : {}) });
|
||||
} else if (child.tagName === 'option') {
|
||||
const key = child.getAttribute('key');
|
||||
const value = child.getAttribute('value');
|
||||
if (key !== null && value !== null) {
|
||||
options[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
widgets.push({ id, type, x, y, w, h, signals, options });
|
||||
}
|
||||
|
||||
return { name, version, widgets };
|
||||
}
|
||||
Reference in New Issue
Block a user