check-whitespace: normalize javascript files

This commit is contained in:
Andrej730
2026-09-14 11:33:51 +05:00
parent 032a361d16
commit 0c12d2334b
18 changed files with 119 additions and 117 deletions
+2
View File
@@ -297,6 +297,8 @@ PATTERNS = (
"*/CMakeLists.txt", "*/CMakeLists.txt",
"*.yml", "*.yml",
"*.yaml", "*.yaml",
"*.ts",
"*.js",
"*.bat", "*.bat",
"*.cmd", "*.cmd",
"*.sh", "*.sh",
@@ -268,7 +268,7 @@ function toggleClientList() {
const clientNumbers = $("<div>") const clientNumbers = $("<div>")
.addClass("client-detail") .addClass("client-detail")
.text( .text(
`${allDrawings[client.ifc_file].drawings.length} Drawing(s), `${allDrawings[client.ifc_file].drawings.length} Drawing(s),
${allDrawings[client.ifc_file].sheets.length} Sheet(s)` ${allDrawings[client.ifc_file].sheets.length} Sheet(s)`
); );
clientDetailsDiv.append(clientNumbers); clientDetailsDiv.append(clientNumbers);
@@ -334,7 +334,7 @@ function toggleClientList() {
const clientNumbers = $("<div>") const clientNumbers = $("<div>")
.addClass("client-detail") .addClass("client-detail")
.text( .text(
`${allDrawings[client.ifc_file].drawings.length} Drawing(s), `${allDrawings[client.ifc_file].drawings.length} Drawing(s),
${allDrawings[client.ifc_file].sheets.length} Sheet(s)` ${allDrawings[client.ifc_file].sheets.length} Sheet(s)`
); );
clientDetailsDiv.append(clientNumbers); clientDetailsDiv.append(clientNumbers);
@@ -75,7 +75,7 @@ function setupPage(workScheduleData){
g.setTotalHeight(""); g.setTotalHeight("");
g.Draw(); g.Draw();
var values = document.getElementById("print_page_size").value.split(",") var values = document.getElementById("print_page_size").value.split(",")
let css = let css =
"@media print {\n @page {\n size: " + values[0] + "mm " + values[1] + "mm;\n }\n"; "@media print {\n @page {\n size: " + values[0] + "mm " + values[1] + "mm;\n }\n";
g.printChart(values[0], values[1], css); g.printChart(values[0], values[1], css);
g.setTotalHeight(900); g.setTotalHeight(900);
@@ -109,4 +109,4 @@ function setupPage(workScheduleData){
let creation_date_string = document.createTextNode("Created: " + new Date(workScheduleData.CreationDate).toLocaleDateString()); let creation_date_string = document.createTextNode("Created: " + new Date(workScheduleData.CreationDate).toLocaleDateString());
creation_date.appendChild(creation_date_string); creation_date.appendChild(creation_date_string);
document.getElementById("schedule-header").appendChild(creation_date); document.getElementById("schedule-header").appendChild(creation_date);
} }
+15 -15
View File
@@ -99,29 +99,29 @@ const PROVIDERS = {
baseUrlPlaceholder: "https://openrouter.ai/api/v1", baseUrlPlaceholder: "https://openrouter.ai/api/v1",
baseUrlDefault: "https://openrouter.ai/api/v1", baseUrlDefault: "https://openrouter.ai/api/v1",
models: [ models: [
{ {
value: "openai/gpt-oss-20b", value: "openai/gpt-oss-20b",
label: "gpt-oss-20b" label: "gpt-oss-20b"
}, },
{ {
value: "openai/gpt-oss-120b", value: "openai/gpt-oss-120b",
label: "gpt-oss-120b" label: "gpt-oss-120b"
}, },
{ {
value: "mistralai/mistral-small-3.2-24b-instruct", value: "mistralai/mistral-small-3.2-24b-instruct",
label: "mistral-small-3.2" label: "mistral-small-3.2"
}, },
{ {
value: "openai/gpt-4.1", value: "openai/gpt-4.1",
label: "gpt-4.1" label: "gpt-4.1"
}, },
{ {
value: "anthropic/claude-sonnet-4-5", value: "anthropic/claude-sonnet-4-5",
label: "claude-sonnet-4-5" label: "claude-sonnet-4-5"
}, },
{ {
value: "google/gemini-2.5-pro-preview", value: "google/gemini-2.5-pro-preview",
label: "gemini-2.5-pro" label: "gemini-2.5-pro"
}, },
], ],
}, },
+3 -3
View File
@@ -25,10 +25,10 @@ async function ensurePyodide() {
await pyodide.loadPackage("numpy"); await pyodide.loadPackage("numpy");
await pyodide.loadPackage("shapely"); await pyodide.loadPackage("shapely");
await pyodide.loadPackage("typing-extensions"); await pyodide.loadPackage("typing-extensions");
const micropip = pyodide.pyimport("micropip"); const micropip = pyodide.pyimport("micropip");
micropip.install("python-dateutil") micropip.install("python-dateutil")
const wheelUrl = "https://ifcopenshell.github.io/wasm-wheels/ifcopenshell-0.8.5-cp313-cp313-pyodide_2025_0_wasm32.whl"; const wheelUrl = "https://ifcopenshell.github.io/wasm-wheels/ifcopenshell-0.8.5-cp313-cp313-pyodide_2025_0_wasm32.whl";
await micropip.install(wheelUrl); await micropip.install(wheelUrl);
@@ -98,4 +98,4 @@ self.onmessage = async (ev) => {
} catch (e) { } catch (e) {
fail(id, e); fail(id, e);
} }
}; };
@@ -34,4 +34,4 @@ export {
Content as DialogContent, Content as DialogContent,
Description as DialogDescription, Description as DialogDescription,
Close as DialogClose, Close as DialogClose,
}; };
@@ -46,4 +46,4 @@ export {
SubContent, SubContent,
SubTrigger, SubTrigger,
Trigger, Trigger,
}; };
@@ -51,4 +51,4 @@ export {
RadioGroup as MenubarRadioGroup, RadioGroup as MenubarRadioGroup,
Label as MenubarLabel, Label as MenubarLabel,
GroupHeading as MenubarGroupHeading, GroupHeading as MenubarGroupHeading,
}; };
@@ -1 +1 @@
export { default as Toaster } from "./sonner.svelte"; export { default as Toaster } from "./sonner.svelte";
@@ -18,4 +18,4 @@ export {
Trigger as TooltipTrigger, Trigger as TooltipTrigger,
Provider as TooltipProvider, Provider as TooltipProvider,
Portal as TooltipPortal, Portal as TooltipPortal,
}; };
@@ -49,7 +49,7 @@ wasm.init().then(async () => {
export async function preloadAutocompletions() { export async function preloadAutocompletions() {
try { try {
const schemas = ["IFC2X3", "IFC4"]; // TODO: IFC4X3 is excluded for now because of an error const schemas = ["IFC2X3", "IFC4"]; // TODO: IFC4X3 is excluded for now because of an error
// Entity classes // Entity classes
const entitySets = await Promise.all( const entitySets = await Promise.all(
schemas.map(schema => wasm.getAllEntityClasses(schema)) schemas.map(schema => wasm.getAllEntityClasses(schema))
@@ -60,7 +60,7 @@ export async function preloadAutocompletions() {
allEntities.add(entity.toUpperCase()); allEntities.add(entity.toUpperCase());
} }
} }
// Data types // Data types
const dataTypeSets = await Promise.all( const dataTypeSets = await Promise.all(
schemas.map(schema => wasm.getAllDataTypes(schema)) schemas.map(schema => wasm.getAllDataTypes(schema))
@@ -71,20 +71,20 @@ export async function preloadAutocompletions() {
allDataTypes.add(dataType); allDataTypes.add(dataType);
} }
} }
// Material categories and Classification systems // Material categories and Classification systems
const [materialCategories, classificationSystems] = await Promise.all([ const [materialCategories, classificationSystems] = await Promise.all([
wasm.getMaterialCategories(), wasm.getMaterialCategories(),
wasm.getStandardClassificationSystems() wasm.getStandardClassificationSystems()
]) as [string[], AutocompletionState["classificationSystems"]]; ]) as [string[], AutocompletionState["classificationSystems"]];
// Cache autocompletions // Cache autocompletions
Autocompletions.entityClasses = Array.from(allEntities).sort(); Autocompletions.entityClasses = Array.from(allEntities).sort();
Autocompletions.materialCategories = materialCategories; Autocompletions.materialCategories = materialCategories;
Autocompletions.classificationSystems = classificationSystems; Autocompletions.classificationSystems = classificationSystems;
Autocompletions.dataTypes = Array.from(allDataTypes).sort(); Autocompletions.dataTypes = Array.from(allDataTypes).sort();
Autocompletions.isLoaded = true; Autocompletions.isLoaded = true;
console.log('Autocompletions preloaded'); console.log('Autocompletions preloaded');
} catch (error) { } catch (error) {
console.error('Failed to preload autocompletions:', error); console.error('Failed to preload autocompletions:', error);
@@ -122,13 +122,13 @@ export function getDataTypes() {
export async function loadIfc(file: File): Promise<IfcModel> { export async function loadIfc(file: File): Promise<IfcModel> {
try { try {
IFCModels.isLoading = true; IFCModels.isLoading = true;
const arrayBuffer = await file.arrayBuffer(); const arrayBuffer = await file.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer); const uint8Array = new Uint8Array(arrayBuffer);
// Load IFC model // Load IFC model
const ifcId = await wasm.loadIfc(Array.from(uint8Array)) as string; const ifcId = await wasm.loadIfc(Array.from(uint8Array)) as string;
// Add to models list // Add to models list
const model: IfcModel = { const model: IfcModel = {
id: ifcId, id: ifcId,
@@ -137,7 +137,7 @@ export async function loadIfc(file: File): Promise<IfcModel> {
loadedAt: new Date() loadedAt: new Date()
}; };
IFCModels.models = [...IFCModels.models, model]; IFCModels.models = [...IFCModels.models, model];
console.log(`IFC model "${file.name}" loaded with ID: ${ifcId}`); console.log(`IFC model "${file.name}" loaded with ID: ${ifcId}`);
return model; return model;
} catch (error) { } catch (error) {
@@ -152,10 +152,10 @@ export async function unloadIfc(modelId: string) {
try { try {
// Unload model // Unload model
await wasm.unloadIfc(modelId); await wasm.unloadIfc(modelId);
// Remove from models list // Remove from models list
IFCModels.models = IFCModels.models.filter(model => model.id !== modelId); IFCModels.models = IFCModels.models.filter(model => model.id !== modelId);
console.log(`IFC model with ID ${modelId} unloaded`); console.log(`IFC model with ID ${modelId} unloaded`);
} catch (error) { } catch (error) {
console.error('Failed to unload IFC model:', error); console.error('Failed to unload IFC model:', error);
@@ -173,10 +173,10 @@ export async function auditIfc(modelId: string, idsData: string | Uint8Array | A
} else { } else {
idsBytes = idsData; idsBytes = idsData;
} }
// Run audit // Run audit
const auditResult = await wasm.auditIfc(modelId, idsBytes) as { json: AuditReportData; html: string }; const auditResult = await wasm.auditIfc(modelId, idsBytes) as { json: AuditReportData; html: string };
console.log(`Audit completed for model ${modelId}`); console.log(`Audit completed for model ${modelId}`);
return auditResult; return auditResult;
} catch (error) { } catch (error) {
@@ -194,7 +194,7 @@ export async function openIfc() {
const fileInput = document.createElement('input'); const fileInput = document.createElement('input');
fileInput.type = 'file'; fileInput.type = 'file';
fileInput.accept = '.ifc'; fileInput.accept = '.ifc';
fileInput.onchange = async (event) => { fileInput.onchange = async (event) => {
const target = event.target as HTMLInputElement | null; const target = event.target as HTMLInputElement | null;
const file = target?.files?.[0]; const file = target?.files?.[0];
@@ -202,13 +202,13 @@ export async function openIfc() {
reject(new Error('No file selected')); reject(new Error('No file selected'));
return; return;
} }
// Check if it's an IFC file // Check if it's an IFC file
if (!file.name.toLowerCase().endsWith('.ifc')) { if (!file.name.toLowerCase().endsWith('.ifc')) {
reject(new Error('Please select a valid IFC file (.ifc)')); reject(new Error('Please select a valid IFC file (.ifc)'));
return; return;
} }
try { try {
await loadIfc(file); await loadIfc(file);
resolve(); resolve();
@@ -216,7 +216,7 @@ export async function openIfc() {
reject(error); reject(error);
} }
}; };
fileInput.onerror = () => reject(new Error('Failed to open file picker')); fileInput.onerror = () => reject(new Error('Failed to open file picker'));
fileInput.click(); fileInput.click();
}); });
@@ -234,7 +234,7 @@ export function createAuditReport(
): AuditReport | undefined { ): AuditReport | undefined {
const model = getIfcById(modelId); const model = getIfcById(modelId);
if (!model) return; if (!model) return;
const auditReport: AuditReport = { const auditReport: AuditReport = {
id: id(), id: id(),
modelId: modelId, modelId: modelId,
@@ -244,7 +244,7 @@ export function createAuditReport(
data: auditData, data: auditData,
htmlReport: htmlReport htmlReport: htmlReport
}; };
IFCModels.audits.unshift(auditReport); IFCModels.audits.unshift(auditReport);
return auditReport; return auditReport;
} }
@@ -266,7 +266,7 @@ export async function downloadAuditReport(auditId: string) {
if (!audit || !audit.htmlReport) { if (!audit || !audit.htmlReport) {
throw new Error('HTML report not available for this audit'); throw new Error('HTML report not available for this audit');
} }
// Get IDS document title for filename // Get IDS document title for filename
let filename = 'report.html'; let filename = 'report.html';
if (audit.document && IDS.Module.documents[audit.document]) { if (audit.document && IDS.Module.documents[audit.document]) {
@@ -274,15 +274,15 @@ export async function downloadAuditReport(auditId: string) {
const title = doc.info?.title || 'untitled'; const title = doc.info?.title || 'untitled';
filename = `report_${title.replace(/[^a-z0-9]/gi, '_').toLowerCase()}.html`; filename = `report_${title.replace(/[^a-z0-9]/gi, '_').toLowerCase()}.html`;
} }
const blob = new Blob([audit.htmlReport], { type: 'text/html' }); const blob = new Blob([audit.htmlReport], { type: 'text/html' });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
const link = document.createElement('a'); const link = document.createElement('a');
link.href = url; link.href = url;
link.download = filename; link.download = filename;
link.style.display = 'none'; link.style.display = 'none';
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
document.body.removeChild(link); document.body.removeChild(link);
@@ -293,47 +293,47 @@ export async function runAudit() {
if (IFCModels.models.length === 0) { if (IFCModels.models.length === 0) {
throw new Error('Please load an IFC model first'); throw new Error('Please load an IFC model first');
} }
if (!IDS.Module.activeDocument) { if (!IDS.Module.activeDocument) {
throw new Error('Please create or open an IDS document first'); throw new Error('Please create or open an IDS document first');
} }
// Clear previous audit reports // Clear previous audit reports
IFCModels.audits = []; IFCModels.audits = [];
// Get the active IDS document XML // Get the active IDS document XML
const idsXml = await IDS.exportActiveDocument(); const idsXml = await IDS.exportActiveDocument();
if (!idsXml) { if (!idsXml) {
throw new Error('Failed to export IDS document'); throw new Error('Failed to export IDS document');
} }
// Run audit on all loaded models // Run audit on all loaded models
let firstAuditReport: AuditReport | undefined; let firstAuditReport: AuditReport | undefined;
for (const model of IFCModels.models) { for (const model of IFCModels.models) {
const result = await auditIfc(model.id, idsXml); const result = await auditIfc(model.id, idsXml);
// Extract JSON and HTML reports from the result // Extract JSON and HTML reports from the result
const jsonData = result.json || null; const jsonData = result.json || null;
const htmlReport = result.html || null; const htmlReport = result.html || null;
if (!jsonData) { if (!jsonData) {
continue; continue;
} }
const auditReport = createAuditReport(model.id, IDS.Module.activeDocument as string, jsonData, htmlReport); const auditReport = createAuditReport(model.id, IDS.Module.activeDocument as string, jsonData, htmlReport);
// Store the first audit report to open in viewer // Store the first audit report to open in viewer
if (!firstAuditReport) { if (!firstAuditReport) {
firstAuditReport = auditReport; firstAuditReport = auditReport;
} }
} }
// Switch to viewer mode and set the first audit report as active // Switch to viewer mode and set the first audit report as active
if (firstAuditReport && IDS.Module.activeDocument) { if (firstAuditReport && IDS.Module.activeDocument) {
IDS.setDocumentState(IDS.Module.activeDocument, { IDS.setDocumentState(IDS.Module.activeDocument, {
viewMode: 'viewer', viewMode: 'viewer',
auditReport: firstAuditReport.id auditReport: firstAuditReport.id
}); });
} }
return firstAuditReport; return firstAuditReport;
} }
@@ -59,33 +59,33 @@ export const connect = () => new Promise<void>((resolve, reject) => {
resolve(); resolve();
return; return;
} }
try { try {
Bonsai.socket = io(`ws://127.0.0.1:${Bonsai.port}/ifctester`, { Bonsai.socket = io(`ws://127.0.0.1:${Bonsai.port}/ifctester`, {
transports: ['websocket'], transports: ['websocket'],
reconnection: false, reconnection: false,
timeout: 5000 timeout: 5000
}); });
Bonsai.socket.on('connect', () => { Bonsai.socket.on('connect', () => {
Bonsai.connected = true; Bonsai.connected = true;
success('Connected to Bonsai'); success('Connected to Bonsai');
resolve(); resolve();
}); });
Bonsai.socket.on('disconnect', () => { Bonsai.socket.on('disconnect', () => {
Bonsai.connected = false; Bonsai.connected = false;
}); });
Bonsai.socket.on('connect_error', (err: Error) => { Bonsai.socket.on('connect_error', (err: Error) => {
Bonsai.connected = false; Bonsai.connected = false;
error(`Failed to connect to Bonsai: ${err.message}`); error(`Failed to connect to Bonsai: ${err.message}`);
reject(err); reject(err);
}); });
Bonsai.socket.on('audit_result', handleAuditResult); Bonsai.socket.on('audit_result', handleAuditResult);
Bonsai.socket.on('error', handleAuditError); Bonsai.socket.on('error', handleAuditError);
} catch (err) { } catch (err) {
const message = err instanceof Error ? err.message : String(err); const message = err instanceof Error ? err.message : String(err);
error(`Failed to connect to Bonsai: ${message}`); error(`Failed to connect to Bonsai: ${message}`);
@@ -113,35 +113,35 @@ export const runAudit = async () => {
if (!Bonsai.socket || !Bonsai.connected || !IDS.Module.activeDocument) { if (!Bonsai.socket || !Bonsai.connected || !IDS.Module.activeDocument) {
return null; return null;
} }
try { try {
Bonsai.auditing = true; Bonsai.auditing = true;
const activeDoc = IDS.Module.documents[IDS.Module.activeDocument]; const activeDoc = IDS.Module.documents[IDS.Module.activeDocument];
if (!activeDoc) throw new Error('No active IDS document'); if (!activeDoc) throw new Error('No active IDS document');
// Convert IDS document to XML string // Convert IDS document to XML string
const idsXml = await IDS.exportActiveDocument(); const idsXml = await IDS.exportActiveDocument();
if (!idsXml) { if (!idsXml) {
throw new Error('Failed to export IDS document'); throw new Error('Failed to export IDS document');
} }
const requestId = id(); const requestId = id();
const socket = Bonsai.socket; const socket = Bonsai.socket;
if (!socket) { if (!socket) {
throw new Error('Bonsai socket not connected'); throw new Error('Bonsai socket not connected');
} }
return new Promise<string | null>((resolve, reject) => { return new Promise<string | null>((resolve, reject) => {
// Store request with resolve/reject functions // Store request with resolve/reject functions
pendingAudits.set(requestId, { resolve, reject }); pendingAudits.set(requestId, { resolve, reject });
socket.emit('audit_ids', { socket.emit('audit_ids', {
id: requestId, id: requestId,
ids: idsXml ids: idsXml
}); });
}); });
} catch (err) { } catch (err) {
Bonsai.auditing = false; Bonsai.auditing = false;
const message = err instanceof Error ? err.message : String(err); const message = err instanceof Error ? err.message : String(err);
@@ -156,19 +156,19 @@ export const runAudit = async () => {
*/ */
const handleAuditResult = (data: AuditResultPayload) => { const handleAuditResult = (data: AuditResultPayload) => {
if (!data.id || !data.json_report) return; if (!data.id || !data.json_report) return;
const pendingAudit = pendingAudits.get(data.id); const pendingAudit = pendingAudits.get(data.id);
if (!pendingAudit) { if (!pendingAudit) {
console.warn('[Bonsai] Received response for unknown audit ID:', data.id); console.warn('[Bonsai] Received response for unknown audit ID:', data.id);
return; return;
} }
pendingAudits.delete(data.id); pendingAudits.delete(data.id);
const { resolve } = pendingAudit; const { resolve } = pendingAudit;
try { try {
const reportData = JSON.parse(data.json_report) as AuditReportData; const reportData = JSON.parse(data.json_report) as AuditReportData;
const auditReport: AuditReport = { const auditReport: AuditReport = {
id: data.id, id: data.id,
modelId: `bonsai:${data.id}`, modelId: `bonsai:${data.id}`,
@@ -178,16 +178,16 @@ const handleAuditResult = (data: AuditResultPayload) => {
data: reportData, data: reportData,
htmlReport: data.html_report htmlReport: data.html_report
}; };
// Store audit report // Store audit report
IFCModels.audits.unshift(auditReport); IFCModels.audits.unshift(auditReport);
Bonsai.auditing = false; Bonsai.auditing = false;
success('Audit completed (Bonsai)'); success('Audit completed (Bonsai)');
// Resolve promise with audit ID // Resolve promise with audit ID
resolve(data.id); resolve(data.id);
} catch (err) { } catch (err) {
Bonsai.auditing = false; Bonsai.auditing = false;
const message = err instanceof Error ? err.message : String(err); const message = err instanceof Error ? err.message : String(err);
@@ -202,16 +202,16 @@ const handleAuditResult = (data: AuditResultPayload) => {
*/ */
const handleAuditError = (data: AuditErrorPayload) => { const handleAuditError = (data: AuditErrorPayload) => {
if (!data.id) return; if (!data.id) return;
const pendingAudit = pendingAudits.get(data.id); const pendingAudit = pendingAudits.get(data.id);
if (!pendingAudit) { if (!pendingAudit) {
console.warn('[Bonsai] Received error for unknown audit ID:', data.id); console.warn('[Bonsai] Received error for unknown audit ID:', data.id);
return; return;
} }
pendingAudits.delete(data.id); pendingAudits.delete(data.id);
const { resolve } = pendingAudit; const { resolve } = pendingAudit;
Bonsai.auditing = false; Bonsai.auditing = false;
error(`Audit failed (Bonsai): ${data.error ?? "Unknown error"}`); error(`Audit failed (Bonsai): ${data.error ?? "Unknown error"}`);
resolve(null); resolve(null);
@@ -55,7 +55,7 @@ export async function createDocument() {
export async function deleteDocument(id: string) { export async function deleteDocument(id: string) {
// Clear any audit reports generated using this IDS document // Clear any audit reports generated using this IDS document
clearIdsAuditReports(id); clearIdsAuditReports(id);
delete Module.documents[id]; delete Module.documents[id];
delete Module.states[id]; delete Module.states[id];
@@ -73,18 +73,18 @@ export async function deleteDocument(id: string) {
// We need this because the backend exports with xs: prefix, yet expects a dict without prefixes. // We need this because the backend exports with xs: prefix, yet expects a dict without prefixes.
function normalizeIdsDict(obj: unknown): unknown { function normalizeIdsDict(obj: unknown): unknown {
if (typeof obj !== 'object' || obj === null) return obj; if (typeof obj !== 'object' || obj === null) return obj;
if (Array.isArray(obj)) { if (Array.isArray(obj)) {
return obj.map(normalizeIdsDict); return obj.map(normalizeIdsDict);
} }
const result: Record<string, unknown> = {}; const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(obj)) { for (const [key, value] of Object.entries(obj)) {
if (key === 'xs:restriction' && Array.isArray(value) && value.length > 0) { if (key === 'xs:restriction' && Array.isArray(value) && value.length > 0) {
// Convert xs:restriction array to restriction object // Convert xs:restriction array to restriction object
const restriction = value[0] as Record<string, unknown>; const restriction = value[0] as Record<string, unknown>;
const newRestriction: Record<string, unknown> = {}; const newRestriction: Record<string, unknown> = {};
for (const [restrictionKey, restrictionValue] of Object.entries(restriction)) { for (const [restrictionKey, restrictionValue] of Object.entries(restriction)) {
if (restrictionKey.startsWith('xs:')) { if (restrictionKey.startsWith('xs:')) {
// Remove xs: prefix from keys // Remove xs: prefix from keys
@@ -94,13 +94,13 @@ function normalizeIdsDict(obj: unknown): unknown {
newRestriction[restrictionKey] = restrictionValue; newRestriction[restrictionKey] = restrictionValue;
} }
} }
result.restriction = newRestriction; result.restriction = newRestriction;
} else { } else {
result[key] = normalizeIdsDict(value); result[key] = normalizeIdsDict(value);
} }
} }
return result; return result;
} }
@@ -111,7 +111,7 @@ export async function openDocument() {
}; };
fileInput.type = 'file'; fileInput.type = 'file';
fileInput.accept = '.ids,.xml'; fileInput.accept = '.ids,.xml';
fileInput.onchange = async (event) => { fileInput.onchange = async (event) => {
const target = event.target as HTMLInputElement | null; const target = event.target as HTMLInputElement | null;
const file = target?.files?.[0]; const file = target?.files?.[0];
@@ -119,7 +119,7 @@ export async function openDocument() {
reject(new Error('No file selected')); reject(new Error('No file selected'));
return; return;
} }
try { try {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = async (e) => { reader.onload = async (e) => {
@@ -130,10 +130,10 @@ export async function openDocument() {
// Add document to list and set as active // Add document to list and set as active
Module.documents[docId] = doc; Module.documents[docId] = doc;
// Initialize document state and switch to viewer mode // Initialize document state and switch to viewer mode
setDocumentState(docId, { viewMode: 'viewer' }); setDocumentState(docId, { viewMode: 'viewer' });
Module.activeDocument = docId; Module.activeDocument = docId;
resolve(); resolve();
@@ -147,11 +147,11 @@ export async function openDocument() {
reject(error); reject(error);
} }
}; };
fileInput.oncancel = () => { fileInput.oncancel = () => {
reject(new Error('File selection cancelled')); reject(new Error('File selection cancelled'));
}; };
// Trigger the file dialog // Trigger the file dialog
fileInput.click(); fileInput.click();
}); });
@@ -175,7 +175,7 @@ export async function exportDocument(docId: string) {
} }
const xmlString = await wasm.exportIDS(doc as Record<string, unknown>) as string; const xmlString = await wasm.exportIDS(doc as Record<string, unknown>) as string;
// Create and download file // Create and download file
const blob = new Blob([xmlString], { type: 'application/xml' }); const blob = new Blob([xmlString], { type: 'application/xml' });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
@@ -290,7 +290,7 @@ export function stringifyFacet(
const usage = getSpecUsage(spec); const usage = getSpecUsage(spec);
const descriptions: string[] = []; const descriptions: string[] = [];
// Entity facet // Entity facet
if (facetType === "entity") { if (facetType === "entity") {
if (clauseType === "applicability") { if (clauseType === "applicability") {
@@ -377,13 +377,13 @@ export function stringifyFacet(
if (clauseType === "requirements" && "@cardinality" in facet && facet["@cardinality"] === "prohibited") { if (clauseType === "requirements" && "@cardinality" in facet && facet["@cardinality"] === "prohibited") {
isProhibited = !isProhibited; isProhibited = !isProhibited;
} }
if (isProhibited) if (isProhibited)
combined = combined.replace("Shall", "Shall not").replace("shall", "shall not"); combined = combined.replace("Shall", "Shall not").replace("shall", "shall not");
if (clauseType === "requirements" && "@cardinality" in facet && facet["@cardinality"] === "optional") if (clauseType === "requirements" && "@cardinality" in facet && facet["@cardinality"] === "optional")
combined = combined.replace("Shall", "May").replace("shall", "may"); combined = combined.replace("Shall", "May").replace("shall", "may");
return renderFacetString(combined); return renderFacetString(combined);
} }
@@ -398,27 +398,27 @@ function stringifyValue(value?: FacetValue) {
// Converts restriction objects to human-readable strings // Converts restriction objects to human-readable strings
function stringifyRestriction(restriction: Restriction) { function stringifyRestriction(restriction: Restriction) {
if (!restriction) return ""; if (!restriction) return "";
// Handle enumeration // Handle enumeration
if (restriction.enumeration && Array.isArray(restriction.enumeration)) { if (restriction.enumeration && Array.isArray(restriction.enumeration)) {
const values = restriction.enumeration.map(item => `**${item['@value']}**` || '').filter(v => v); const values = restriction.enumeration.map(item => `**${item['@value']}**` || '').filter(v => v);
return values.length > 0 ? `is one of ${values.join(", ")}` : "has enumeration restriction"; return values.length > 0 ? `is one of ${values.join(", ")}` : "has enumeration restriction";
} }
// Handle pattern // Handle pattern
if (restriction.pattern && Array.isArray(restriction.pattern) && restriction.pattern.length > 0) { if (restriction.pattern && Array.isArray(restriction.pattern) && restriction.pattern.length > 0) {
const pattern = `\`${restriction.pattern[0]['@value']}\`` || ''; const pattern = `\`${restriction.pattern[0]['@value']}\`` || '';
return pattern ? `matches pattern ${pattern}` : "has pattern restriction"; return pattern ? `matches pattern ${pattern}` : "has pattern restriction";
} }
// Handle length restrictions // Handle length restrictions
if (restriction.length && Array.isArray(restriction.length) && restriction.length.length > 0) { if (restriction.length && Array.isArray(restriction.length) && restriction.length.length > 0) {
const length = `**${restriction.length[0]['@value']}**` || ''; const length = `**${restriction.length[0]['@value']}**` || '';
return length ? `has length ${length}` : "has length restriction"; return length ? `has length ${length}` : "has length restriction";
} }
// Handle range restrictions // Handle range restrictions
if (restriction.minInclusive || restriction.maxInclusive || if (restriction.minInclusive || restriction.maxInclusive ||
restriction.minExclusive || restriction.maxExclusive) { restriction.minExclusive || restriction.maxExclusive) {
const parts = []; const parts = [];
if (restriction.minInclusive && restriction.minInclusive.length > 0) { if (restriction.minInclusive && restriction.minInclusive.length > 0) {
@@ -435,7 +435,7 @@ function stringifyRestriction(restriction: Restriction) {
} }
return parts.length > 0 ? `is in range ${parts.join(", ")}` : "has range restriction"; return parts.length > 0 ? `is in range ${parts.join(", ")}` : "has range restriction";
} }
// Handle length range restrictions // Handle length range restrictions
if (restriction.minLength || restriction.maxLength) { if (restriction.minLength || restriction.maxLength) {
const parts = []; const parts = [];
@@ -447,16 +447,16 @@ function stringifyRestriction(restriction: Restriction) {
} }
return parts.length > 0 ? `has ${parts.join(", ")}` : "has length range restriction"; return parts.length > 0 ? `has ${parts.join(", ")}` : "has length range restriction";
} }
return "has complex restriction"; return "has complex restriction";
} }
function renderFacetString(text: string): string { function renderFacetString(text: string): string {
// Convert **text** to <strong>text</strong> // Convert **text** to <strong>text</strong>
const withStrong = text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>'); const withStrong = text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
// Convert `text` to <code>text</code> // Convert `text` to <code>text</code>
const withCode = withStrong.replace(/`([^`]+)`/g, '<code>$1</code>'); const withCode = withStrong.replace(/`([^`]+)`/g, '<code>$1</code>');
return withCode; return withCode;
} }
@@ -75,7 +75,7 @@ class WASMModule extends EventEmitter {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.pendingMessages.set(id, { resolve, reject }); this.pendingMessages.set(id, { resolve, reject });
worker.postMessage({ worker.postMessage({
type, type,
payload, payload,
@@ -86,7 +86,7 @@ class WASMModule extends EventEmitter {
_handleWorkerMessage({ type, payload, id }: WorkerResponse) { _handleWorkerMessage({ type, payload, id }: WorkerResponse) {
const pendingMessage = this.pendingMessages.get(id); const pendingMessage = this.pendingMessages.get(id);
if (!pendingMessage) { if (!pendingMessage) {
console.warn('[WASM] Received response for unknown message ID:', id); console.warn('[WASM] Received response for unknown message ID:', id);
return; return;
@@ -16,7 +16,7 @@ let PartOf: any;
export async function init(pdide: any) { export async function init(pdide: any) {
pyodide = pdide; pyodide = pdide;
await pyodide.loadPackagesFromImports(` await pyodide.loadPackagesFromImports(`
import ifctester.ids import ifctester.ids
import ifctester.facet import ifctester.facet
@@ -25,7 +25,7 @@ export async function init(pdide: any) {
// Import the core IDS classes // Import the core IDS classes
Ids = pyodide.pyimport("ifctester.ids").Ids; Ids = pyodide.pyimport("ifctester.ids").Ids;
Specification = pyodide.pyimport("ifctester.ids").Specification; Specification = pyodide.pyimport("ifctester.ids").Specification;
// Import facet classes // Import facet classes
Entity = pyodide.pyimport("ifctester.facet").Entity; Entity = pyodide.pyimport("ifctester.facet").Entity;
Attribute = pyodide.pyimport("ifctester.facet").Attribute; Attribute = pyodide.pyimport("ifctester.facet").Attribute;
@@ -56,13 +56,13 @@ export function validateIDS(idsObj: Record<string, unknown>): boolean {
const ids_raw = _idsToInstance(idsObj) const ids_raw = _idsToInstance(idsObj)
const tempFilename = `temp_${Date.now()}.xml`; const tempFilename = `temp_${Date.now()}.xml`;
const isValid = ids_raw.to_xml(tempFilename); // to_xml validates the XML as well, as far as I understand const isValid = ids_raw.to_xml(tempFilename); // to_xml validates the XML as well, as far as I understand
pyodide.runPython(` pyodide.runPython(`
import os import os
if os.path.exists("${tempFilename}"): if os.path.exists("${tempFilename}"):
os.remove("${tempFilename}") os.remove("${tempFilename}")
`); `);
return isValid; return isValid;
} }
+1 -1
View File
@@ -3,4 +3,4 @@
*/ */
export {default as Home} from './Home/index.svelte'; export {default as Home} from './Home/index.svelte';
export {default as NotFound} from './NotFound/index.svelte'; export {default as NotFound} from './NotFound/index.svelte';
+1 -1
View File
@@ -5,4 +5,4 @@ const routes = {
'*': NotFound, '*': NotFound,
}; };
export default routes; export default routes;