mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
87 lines
1.8 KiB
JavaScript
87 lines
1.8 KiB
JavaScript
const ROW_REGEX =
|
|
/^\|\s*(\d+(?:\.\d+){2,3})\s*\|\s*([^|]+?)\s*\|\s*([^|]+?)\s*\|\s*([^|]+?)\s*\|\s*([^|]+?)\s*\|\s*([^|]*?)\s*\|\s*$/u;
|
|
|
|
const ID_REGEX = /^\d+(?:\.\d+){2,3}$/;
|
|
|
|
const VALID_STATUS = new Set(["✅", "🟡", "❌", "🚫"]);
|
|
|
|
export function parseMatrix(markdown) {
|
|
if (typeof markdown !== "string") {
|
|
return {
|
|
rows: [],
|
|
errors: ["Input must be a string"],
|
|
};
|
|
}
|
|
|
|
const rows = [];
|
|
const errors = [];
|
|
|
|
const lines = markdown.split(/\r?\n/);
|
|
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const line = lines[i];
|
|
|
|
const match = ROW_REGEX.exec(line);
|
|
if (!match) continue;
|
|
|
|
const [, id, name, layer, path, rawStatus, notes] = match;
|
|
|
|
const status = rawStatus.trim();
|
|
|
|
if (!ID_REGEX.test(id)) {
|
|
errors.push(`Line ${i + 1}: Invalid ID format "${id}"`);
|
|
continue;
|
|
}
|
|
|
|
if (!VALID_STATUS.has(status)) {
|
|
errors.push(`Line ${i + 1} (${id}): invalid status "${status}"`);
|
|
continue;
|
|
}
|
|
|
|
rows.push({
|
|
id,
|
|
name: name.trim(),
|
|
layer: layer.trim(),
|
|
path: path.trim(),
|
|
status,
|
|
notes: notes.trim(),
|
|
});
|
|
}
|
|
|
|
return { rows, errors };
|
|
}
|
|
|
|
export function validateAgainstCatalog(rows, catalogIds) {
|
|
const counts = new Map();
|
|
|
|
for (const { id } of rows) {
|
|
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
}
|
|
|
|
const duplicates = [];
|
|
|
|
for (const [id, count] of counts) {
|
|
if (count > 1) {
|
|
duplicates.push(id);
|
|
}
|
|
}
|
|
|
|
const catalogSet =
|
|
catalogIds instanceof Set ? catalogIds : new Set(catalogIds);
|
|
|
|
const missingFromMatrix = [];
|
|
|
|
for (const id of catalogSet) {
|
|
if (!counts.has(id)) {
|
|
missingFromMatrix.push(id);
|
|
}
|
|
}
|
|
|
|
return {
|
|
missingFromMatrix,
|
|
duplicates,
|
|
totalRows: rows.length,
|
|
uniqueRows: counts.size,
|
|
};
|
|
}
|