project
Adom Custom Electronic Load
Public Made by Adomby adom
Two-layer digitally controlled electronic-load prototype. Compact R11 is under active electrical, cooling and probe-access review; not a manufacturing release.
← Commit history
Optimize project hero GLB while preserving layers and fan animation
8 files changed
+1201−1
mechanical/side-fan-r10/hero-optimization.json+453mechanical/side-fan-r10/side-fan-hero.glbmechanical/side-fan-r10/side-fan-hero_footprint.json+1page.json+1−1tools/hero-optimizer/README.md+9tools/hero-optimizer/optimize.mjs+14tools/hero-optimizer/package-lock.json+705tools/hero-optimizer/package.json+18mechanical/side-fan-r10/hero-optimization.jsonadded+453@@ -0,0 +1,453 @@+{+ "source": "side-fan-assembly.glb",+ "hero": "side-fan-hero.glb",+ "method": "Exact vertex welding followed by Draco compression, 18-bit positions and 12-bit normals. No mesh simplification. Eight zero-area triangles removed by codec. All engineering/simulation inputs retained unchanged.",+ "sourceBytes": 16370056,+ "heroBytes": 1242480,+ "sourceSha256": "c554ca119455a58b0e82110ea0071fd0c3a58f0307e2a6c15797922ecf6417f3",+ "heroSha256": "c602831513d7cdd164b015e8c8590109b44a81f0f7e5eb16da4c473c014711bf",+ "verticesBefore": 304717,+ "verticesAfterWeld": 292270,+ "metadata": {+ "metadataExact": true,+ "issues": {+ "numErrors": 0,+ "numWarnings": 0,+ "numInfos": 30,+ "numHints": 0,+ "messages": [+ {+ "code": "UNSUPPORTED_EXTENSION",+ "message": "Cannot validate an extension as it is not supported by the validator: 'KHR_draco_mesh_compression'.",+ "severity": 2,+ "pointer": "/extensionsUsed/0"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/1"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/2"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/3"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/4"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/5"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/6"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/7"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/8"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/9"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/10"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/11"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/12"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/13"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/14"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/15"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/16"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/17"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/18"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/19"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/20"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/21"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/22"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/23"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/24"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/25"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/26"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/27"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/28"+ },+ {+ "code": "UNUSED_OBJECT",+ "message": "This object may be unused.",+ "severity": 2,+ "pointer": "/bufferViews/29"+ }+ ],+ "truncated": true+ }+ },+ "geometry": {+ "maxLocalPositionError": 6.135515800694357e-06,+ "triangleCounts": [+ 310648,+ 310640+ ],+ "degenerateTriangleRemoval": [+ {+ "mesh": "SOLID",+ "removedTriangles": 2,+ "originalZeroAreaTriangles": 2+ },+ {+ "mesh": "SOLID",+ "removedTriangles": 2,+ "originalZeroAreaTriangles": 2+ },+ {+ "mesh": "SOLID",+ "removedTriangles": 2,+ "originalZeroAreaTriangles": 2+ },+ {+ "mesh": "SOLID",+ "removedTriangles": 2,+ "originalZeroAreaTriangles": 2+ }+ ],+ "assetExtrasPreserved": true+ },+ "canonicalViewer": [+ {+ "kind": "original",+ "errors": [],+ "vertices": 307382,+ "meshes": 399,+ "layers": [+ {+ "name": "components",+ "label": "Board components",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "masked_copper",+ "label": "Copper traces under mask",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "pads",+ "label": "Exposed pads",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "vias",+ "label": "Vias",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "solder_mask",+ "label": "Solder mask",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "substrate",+ "label": "PCB substrate",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "fan",+ "label": "Fan housing and rotor",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "carrier",+ "label": "Carrier frame and clamps",+ "group": "Mechanics",+ "visible": true,+ "declared": true+ },+ {+ "name": "fan_bracket",+ "label": "Fan bracket and gussets",+ "group": "Mechanics",+ "visible": true,+ "declared": true+ },+ {+ "name": "heatsink",+ "label": "Heatsink",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "sink_supports",+ "label": "Heatsink supports",+ "group": "Mechanics",+ "visible": true,+ "declared": true+ },+ {+ "name": "thermal_interface",+ "label": "Q1 thermal interface / fastener",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "guard",+ "label": "Fan guard and bolts",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "harness",+ "label": "Fan wiring and connector",+ "group": "Cooling",+ "visible": true,+ "declared": true+ }+ ],+ "animations": [+ "Fan.Rotor.Revolution"+ ]+ },+ {+ "kind": "optimized",+ "errors": [],+ "vertices": 294990,+ "meshes": 399,+ "layers": [+ {+ "name": "components",+ "label": "Board components",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "masked_copper",+ "label": "Copper traces under mask",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "pads",+ "label": "Exposed pads",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "vias",+ "label": "Vias",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "solder_mask",+ "label": "Solder mask",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "substrate",+ "label": "PCB substrate",+ "group": "PCB",+ "visible": true,+ "declared": true+ },+ {+ "name": "fan",+ "label": "Fan housing and rotor",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "carrier",+ "label": "Carrier frame and clamps",+ "group": "Mechanics",+ "visible": true,+ "declared": true+ },+ {+ "name": "fan_bracket",+ "label": "Fan bracket and gussets",+ "group": "Mechanics",+ "visible": true,+ "declared": true+ },+ {+ "name": "heatsink",+ "label": "Heatsink",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "sink_supports",+ "label": "Heatsink supports",+ "group": "Mechanics",+ "visible": true,+ "declared": true+ },+ {+ "name": "thermal_interface",+ "label": "Q1 thermal interface / fastener",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "guard",+ "label": "Fan guard and bolts",+ "group": "Cooling",+ "visible": true,+ "declared": true+ },+ {+ "name": "harness",+ "label": "Fan wiring and connector",+ "group": "Cooling",+ "visible": true,+ "declared": true+ }+ ],+ "animations": [+ "Fan.Rotor.Revolution"+ ]+ }+ ]+}
mechanical/side-fan-r10/side-fan-hero.glbadded⋯ 1 unchanged line ⋯
mechanical/side-fan-r10/side-fan-hero_footprint.jsonadded+1@@ -0,0 +1 @@+{"boardName": "board", "originalFilename": "board.kicad_pcb", "generatedAt": "2026-10-13T04:05:00.643Z", "boardDimensions": {"width": 72, "height": 104, "bounds": {"minX": 96, "maxX": 168, "minY": -104, "maxY": 0}}, "originPin": {"name": "MachinePinLargeShort", "corner": "FL", "originalName": "1", "elementName": "MP1", "globalPosition": {"x": 100, "y": -100}}, "machinePins": [{"name": "MachinePinLargeShort", "contactType": "large_pin_short", "corner": "FL", "originalName": "1", "elementName": "MP1", "elementValue": "MachinePinLargeShort", "packageName": "Molecule:MachinePinLargeShort", "drillDiameter": 3.45, "elementRot": "R0", "position": {"x": 0, "y": 0}, "globalPosition": {"x": 100, "y": -100}, "z": 5.6}, {"name": "MachinePinLargeShort", "contactType": "large_pin_short", "corner": "FR", "originalName": "1", "elementName": "MP2", "elementValue": "MachinePinLargeShort", "packageName": "Molecule:MachinePinLargeShort", "drillDiameter": 3.45, "elementRot": "R0", "position": {"x": 64, "y": 0}, "globalPosition": {"x": 164, "y": -100}, "z": 5.6}, {"name": "MachinePinLargeShort", "contactType": "large_pin_short", "corner": "BR", "originalName": "1", "elementName": "MP4", "elementValue": "MachinePinLargeShort", "packageName": "Molecule:MachinePinLargeShort", "drillDiameter": 3.45, "elementRot": "R0", "position": {"x": 64, "y": 96}, "globalPosition": {"x": 164, "y": -4}, "z": 5.6}, {"name": "MachinePinLargeShort", "contactType": "large_pin_short", "corner": "BL", "originalName": "1", "elementName": "MP3", "elementValue": "MachinePinLargeShort", "packageName": "Molecule:MachinePinLargeShort", "drillDiameter": 3.45, "elementRot": "R0", "position": {"x": 0, "y": 96}, "globalPosition": {"x": 100, "y": -4}, "z": 5.6}], "contacts": [{"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J6", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 40, "y": 0}, "globalPosition": {"x": 140, "y": -100}, "z": 5.6}, {"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J5", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 36, "y": 0}, "globalPosition": {"x": 136, "y": -100}, "z": 5.6}, {"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J2", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 12, "y": 0}, "globalPosition": {"x": 112, "y": -100}, "z": 5.6}, {"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J4", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 24, "y": 0}, "globalPosition": {"x": 124, "y": -100}, "z": 5.6}, {"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J3", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 20, "y": 0}, "globalPosition": {"x": 120, "y": -100}, "z": 5.6}, {"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J7", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 16, "y": -2}, "globalPosition": {"x": 116, "y": -102}, "z": 5.6}, {"name": "MachineContactMedium", "contactType": "medium_contact", "nameResolution": {"source": "value", "priority": ["value", "name", "pad.number", "elementName"], "reason": "value field was non-empty and not a known placeholder"}, "originalName": "1", "elementName": "J1", "elementValue": "MachineContactMedium", "packageName": "Molecule:MachineContactMedium", "drillDiameter": 0.78, "elementRot": "R0", "position": {"x": 8, "y": 0}, "globalPosition": {"x": 108, "y": -100}, "z": 5.6}], "testPoints": [{"name": "5V_AUX", "reference": "TP14", "size": 1, "position": {"x": 19.75, "y": -2.5}, "globalPosition": {"x": 119.75, "y": -102.5}}, {"name": "VREF_2V5", "reference": "TP15", "size": 1, "position": {"x": 4.5, "y": 37.25}, "globalPosition": {"x": 104.5, "y": -62.75}}, {"name": "SHUNT_N_SENSE", "reference": "TP13", "size": 1, "position": {"x": 8, "y": 34}, "globalPosition": {"x": 108, "y": -66}}, {"name": "GND", "reference": "TP11", "size": 1, "position": {"x": 0, "y": 8}, "globalPosition": {"x": 100, "y": -92}}, {"name": "V_GATE", "reference": "TP6", "size": 1, "position": {"x": 6.8, "y": 17.4}, "globalPosition": {"x": 106.8, "y": -82.6}}, {"name": "3V3", "reference": "TP7", "size": 1, "position": {"x": 0, "y": 11}, "globalPosition": {"x": 100, "y": -89}}, {"name": "I_SET", "reference": "TP4", "size": 1, "position": {"x": 0.8, "y": 22.8}, "globalPosition": {"x": 100.8, "y": -77.2}}, {"name": "SHUNT_P_SENSE", "reference": "TP3", "size": 1, "position": {"x": 0, "y": 14}, "globalPosition": {"x": 100, "y": -86}}, {"name": "LOAD_POS", "reference": "TP2", "size": 1, "position": {"x": 6.8, "y": 20}, "globalPosition": {"x": 106.8, "y": -80}}, {"name": "DUT_POS", "reference": "TP1", "size": 1, "position": {"x": 4, "y": 20}, "globalPosition": {"x": 104, "y": -80}}, {"name": "BOOST_SW", "reference": "TP16", "size": 1, "position": {"x": 48.7, "y": 3}, "globalPosition": {"x": 148.7, "y": -97}}, {"name": "HW_OK", "reference": "TP9", "size": 1, "position": {"x": 4, "y": 14.8}, "globalPosition": {"x": 104, "y": -85.2}}, {"name": "GATE", "reference": "TP5", "size": 1, "position": {"x": 4, "y": 17.4}, "globalPosition": {"x": 104, "y": -82.6}}, {"name": "LATCH_Q", "reference": "TP10", "size": 1, "position": {"x": 6.8, "y": 14.8}, "globalPosition": {"x": 106.8, "y": -85.2}}, {"name": "TEMP_SENSE", "reference": "TP8", "size": 1, "position": {"x": 0.8, "y": 20}, "globalPosition": {"x": 100.8, "y": -80}}, {"name": "FAN_TACH", "reference": "TP12", "size": 1, "position": {"x": 4, "y": 34}, "globalPosition": {"x": 104, "y": -66}}], "summary": {"totalMachinePins": 4, "totalContacts": 7, "totalTestPoints": 16}}
page.json+1−1@@ -35,7 +35,7 @@ "subcategory": "", "body_size": null, "parts": {- "model_3d": "mechanical/side-fan-r10/side-fan-assembly.glb",+ "model_3d": "mechanical/side-fan-r10/side-fan-hero.glb", "datasheet": "docs/project-page/electronic-load-datasheet-r0.pdf", "step": "probing-flow/design-candidate/sidefan-r23.step" },
tools/hero-optimizer/README.mdadded+9@@ -0,0 +1,9 @@+# Hero GLB optimizer++With Node 22 or newer, run `npm ci` in this folder, then `node optimize.mjs`. Dependencies are pinned in package-lock.json.++Creates the display-only side-fan-hero.glb; does not replace the engineering assembly or simulator collision model. Uses glTF Transform weld and Draco (18-bit positions, 12-bit normals). No decimation, flattening, or node joining. Layer tags, hierarchy, materials, animation channels, keyframes, and authored asset metadata are retained.++Validation: `mechanical/side-fan-r10/hero-optimization.json`. Compressed geometry was decoded, compared, and rendered in the canonical viewer. The standard validator reports zero errors/warnings but cannot validate Draco payloads itself; the independent decoder/render checks cover that boundary.++The reduction is primarily download/storage size; decoded GPU geometry remains about 0.3 million vertices. No frame-rate or peak-memory improvement is claimed.
tools/hero-optimizer/optimize.mjsadded+14@@ -0,0 +1,14 @@+import {NodeIO} from '@gltf-transform/core';+import {ALL_EXTENSIONS} from '@gltf-transform/extensions';+import {weld,draco} from '@gltf-transform/functions';+import draco3d from 'draco3dgltf';+import fs from 'node:fs';+const base=new URL('../../',import.meta.url).pathname;+const io=new NodeIO().registerExtensions(ALL_EXTENSIONS).registerDependencies({'draco3d.decoder':await draco3d.createDecoderModule(),'draco3d.encoder':await draco3d.createEncoderModule()});+const doc=await io.read(base+'mechanical/side-fan-r10/side-fan-assembly.glb');+const count=()=>doc.getRoot().listMeshes().reduce((n,m)=>n+m.listPrimitives().reduce((n,p)=>n+p.getAttribute('POSITION').getCount(),0),0);+console.log('vertices before',count());await doc.transform(weld());console.log('vertices welded',count());++await doc.transform(draco({method:'edgebreaker',encodeSpeed:5,decodeSpeed:5,quantizePosition:18,quantizeNormal:12}));+await io.write(base+'mechanical/side-fan-r10/side-fan-hero.glb',doc);+console.log('bytes',fs.statSync(base+'mechanical/side-fan-r10/side-fan-hero.glb').size);
tools/hero-optimizer/package-lock.jsonadded+705@@ -0,0 +1,705 @@+{+ "name": "electronic-load-hero-optimizer",+ "lockfileVersion": 3,+ "requires": true,+ "packages": {+ "": {+ "name": "electronic-load-hero-optimizer",+ "dependencies": {+ "@gltf-transform/core": "^4.5.1",+ "@gltf-transform/extensions": "^4.5.1",+ "@gltf-transform/functions": "^4.5.1",+ "@img/sharp-libvips-linux-x64": "^1.3.4",+ "@img/sharp-linux-x64": "^0.35.5",+ "draco3dgltf": "^1.5.7",+ "gltf-validator": "^2.0.0-dev.3.10",+ "meshoptimizer": "^1.3.0"+ },+ "engines": {+ "node": ">=22"+ }+ },+ "node_modules/@emnapi/runtime": {+ "version": "1.11.3",+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",+ "optional": true,+ "dependencies": {+ "tslib": "^2.4.0"+ }+ },+ "node_modules/@gltf-transform/core": {+ "version": "4.5.1",+ "resolved": "https://registry.npmjs.org/@gltf-transform/core/-/core-4.5.1.tgz",+ "integrity": "sha512-OWgBYssKHKoXMIrMb2N20jXqWRnMP9HdtcTFQBEAJtz4P+OOxx5fozl5eAeK7nktIs5uDE/lu4NbkE5VCZaR9g==",+ "dependencies": {+ "property-graph": "^4.1.0"+ },+ "funding": {+ "url": "https://github.com/sponsors/donmccurdy"+ }+ },+ "node_modules/@gltf-transform/extensions": {+ "version": "4.5.1",+ "resolved": "https://registry.npmjs.org/@gltf-transform/extensions/-/extensions-4.5.1.tgz",+ "integrity": "sha512-3jTe+GWRy4fj1TU790LPsO+rpO/4byUWPTpNkjy6M6h8RvrUivRf12Mptc0770K4ZczibpJDNHXZFkFsFMRDLA==",+ "dependencies": {+ "@gltf-transform/core": "^4.5.1",+ "ktx-parse": "^1.1.0"+ },+ "funding": {+ "url": "https://github.com/sponsors/donmccurdy"+ }+ },+ "node_modules/@gltf-transform/functions": {+ "version": "4.5.1",+ "resolved": "https://registry.npmjs.org/@gltf-transform/functions/-/functions-4.5.1.tgz",+ "integrity": "sha512-rfm4nQY2DJ+ip1e15xp7YfQwhRno3kPLcGw4EZiRk1dVwMV3cdFMcF08glYcO/+oLyYkUEs3xXMJYXa0cPgcTg==",+ "dependencies": {+ "@gltf-transform/core": "^4.5.1",+ "@gltf-transform/extensions": "^4.5.1",+ "ktx-parse": "^1.1.0",+ "ndarray": "^1.0.19",+ "ndarray-lanczos": "^0.3.0",+ "ndarray-pixels": "^5.2.0"+ },+ "funding": {+ "url": "https://github.com/sponsors/donmccurdy"+ }+ },+ "node_modules/@img/colour": {+ "version": "1.1.0",+ "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",+ "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",+ "engines": {+ "node": ">=18"+ }+ },+ "node_modules/@img/sharp-darwin-arm64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz",+ "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "darwin"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-darwin-arm64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-darwin-x64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz",+ "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "darwin"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-darwin-x64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-freebsd-wasm32": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz",+ "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==",+ "optional": true,+ "os": [+ "freebsd"+ ],+ "dependencies": {+ "@img/sharp-wasm32": "0.35.5"+ },+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-darwin-arm64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz",+ "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "darwin"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-darwin-x64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz",+ "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "darwin"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linux-arm": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz",+ "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==",+ "cpu": [+ "arm"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linux-arm64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz",+ "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linux-ppc64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz",+ "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==",+ "cpu": [+ "ppc64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linux-riscv64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz",+ "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==",+ "cpu": [+ "riscv64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linux-s390x": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz",+ "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==",+ "cpu": [+ "s390x"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linux-x64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz",+ "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==",+ "cpu": [+ "x64"+ ],+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz",+ "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {+ "version": "1.3.4",+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz",+ "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-linux-arm": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz",+ "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==",+ "cpu": [+ "arm"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linux-arm": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linux-arm64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz",+ "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linux-arm64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linux-ppc64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz",+ "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==",+ "cpu": [+ "ppc64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linux-ppc64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linux-riscv64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz",+ "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==",+ "cpu": [+ "riscv64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linux-riscv64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linux-s390x": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz",+ "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==",+ "cpu": [+ "s390x"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linux-s390x": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linux-x64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz",+ "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==",+ "cpu": [+ "x64"+ ],+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linux-x64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linuxmusl-arm64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz",+ "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-linuxmusl-x64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz",+ "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "linux"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-libvips-linuxmusl-x64": "1.3.4"+ }+ },+ "node_modules/@img/sharp-wasm32": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz",+ "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==",+ "optional": true,+ "dependencies": {+ "@emnapi/runtime": "^1.11.3"+ },+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-webcontainers-wasm32": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz",+ "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==",+ "cpu": [+ "wasm32"+ ],+ "optional": true,+ "dependencies": {+ "@img/sharp-wasm32": "0.35.5"+ },+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-win32-arm64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz",+ "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==",+ "cpu": [+ "arm64"+ ],+ "optional": true,+ "os": [+ "win32"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-win32-ia32": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz",+ "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==",+ "cpu": [+ "ia32"+ ],+ "optional": true,+ "os": [+ "win32"+ ],+ "engines": {+ "node": "^20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@img/sharp-win32-x64": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz",+ "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==",+ "cpu": [+ "x64"+ ],+ "optional": true,+ "os": [+ "win32"+ ],+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ }+ },+ "node_modules/@types/ndarray": {+ "version": "1.1.0",+ "resolved": "https://registry.npmjs.org/@types/ndarray/-/ndarray-1.1.0.tgz",+ "integrity": "sha512-go+C6vHBUuO9jH6Tj6qEZ63JEGoMSxFdmd+6QAtthGD6xumBfIz3RbNDDs2aoRVLf9naH8lk5jnWy2UHHKgYQQ=="+ },+ "node_modules/cwise-compiler": {+ "version": "1.1.3",+ "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz",+ "integrity": "sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ==",+ "dependencies": {+ "uniq": "^1.0.0"+ }+ },+ "node_modules/detect-libc": {+ "version": "2.1.2",+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",+ "engines": {+ "node": ">=8"+ }+ },+ "node_modules/draco3dgltf": {+ "version": "1.5.7",+ "resolved": "https://registry.npmjs.org/draco3dgltf/-/draco3dgltf-1.5.7.tgz",+ "integrity": "sha512-LeqcpmoHIyYUi0z70/H3tMkGj8QhqVxq6FJGPjlzR24BNkQ6jyMheMvFKJBI0dzGZrEOUyQEmZ8axM1xRrbRiw=="+ },+ "node_modules/gltf-validator": {+ "version": "2.0.0-dev.3.10",+ "resolved": "https://registry.npmjs.org/gltf-validator/-/gltf-validator-2.0.0-dev.3.10.tgz",+ "integrity": "sha512-odJ4k0tRkGXiDGn78yDBg+fBbAIvBnXxh3RwAta0emSxGtyagFE8B4xELB1oYe3S5RD8Ci3uZAsZaascH2LAEQ=="+ },+ "node_modules/iota-array": {+ "version": "1.0.0",+ "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz",+ "integrity": "sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA=="+ },+ "node_modules/is-buffer": {+ "version": "1.1.6",+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="+ },+ "node_modules/ktx-parse": {+ "version": "1.1.0",+ "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-1.1.0.tgz",+ "integrity": "sha512-mKp3y+FaYgR7mXWAbyyzpa/r1zDWeaunH+INJO4fou3hb45XuNSwar+7llrRyvpMWafxSIi99RNFJ05MHedaJQ=="+ },+ "node_modules/meshoptimizer": {+ "version": "1.3.0",+ "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.3.0.tgz",+ "integrity": "sha512-2oZqMAcEEiCtXWUjIGtZ71oPx1B0ZxYGTqIKsXB1wzWFhleNsCFxQuUJzgCV706bRcwPWtMGf1odmQvAcqKkIw=="+ },+ "node_modules/ndarray": {+ "version": "1.1.1",+ "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.1.1.tgz",+ "integrity": "sha512-AsE8w/M2MS+0pD3nP5qbRRtJFeJJJaJ+qXZaZr0XjVGXhy6LIj2TERTlkpdK2AI3WufoOP+pwPk3q2ilAJcZ9g==",+ "dependencies": {+ "iota-array": "^1.0.0",+ "is-buffer": "^1.0.2"+ }+ },+ "node_modules/ndarray-lanczos": {+ "version": "0.3.0",+ "resolved": "https://registry.npmjs.org/ndarray-lanczos/-/ndarray-lanczos-0.3.0.tgz",+ "integrity": "sha512-5kBmmG3Zvyj77qxIAC4QFLKuYdDIBJwCG+DukT6jQHNa1Ft74/hPH1z5mbQXeHBt8yvGPBGVrr3wEOdJPYYZYg==",+ "dependencies": {+ "@types/ndarray": "^1.0.11",+ "ndarray": "^1.0.19"+ }+ },+ "node_modules/ndarray-ops": {+ "version": "1.2.2",+ "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz",+ "integrity": "sha512-BppWAFRjMYF7N/r6Ie51q6D4fs0iiGmeXIACKY66fLpnwIui3Wc3CXiD/30mgLbDjPpSLrsqcp3Z62+IcHZsDw==",+ "dependencies": {+ "cwise-compiler": "^1.0.0"+ }+ },+ "node_modules/ndarray-pixels": {+ "version": "5.2.0",+ "resolved": "https://registry.npmjs.org/ndarray-pixels/-/ndarray-pixels-5.2.0.tgz",+ "integrity": "sha512-lTh4tFKziAatVTa9crIsidUyn+lqujVOQpzfdBWvdFu2wo9Uo6z261lVX7SgMyP89xGmj3TMTPbbxl9YDnV4SA==",+ "dependencies": {+ "@types/ndarray": "^1.0.14",+ "ndarray": "^1.0.19",+ "ndarray-ops": "^1.2.2",+ "sharp": "^0.35.0"+ }+ },+ "node_modules/property-graph": {+ "version": "4.1.0",+ "resolved": "https://registry.npmjs.org/property-graph/-/property-graph-4.1.0.tgz",+ "integrity": "sha512-AvPcP7XECNWy4LGmFQ77k7un4lSKM4eS29PTvW4ck95uYeLxXPWJM7hLuBqK91FaHqCcgJvIUCuNJjjxKE7VKQ=="+ },+ "node_modules/semver": {+ "version": "7.8.5",+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",+ "bin": {+ "semver": "bin/semver.js"+ },+ "engines": {+ "node": ">=10"+ }+ },+ "node_modules/sharp": {+ "version": "0.35.5",+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz",+ "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==",+ "dependencies": {+ "@img/colour": "^1.1.0",+ "detect-libc": "^2.1.2",+ "semver": "^7.8.5"+ },+ "engines": {+ "node": ">=20.9.0"+ },+ "funding": {+ "url": "https://opencollective.com/libvips"+ },+ "optionalDependencies": {+ "@img/sharp-darwin-arm64": "0.35.5",+ "@img/sharp-darwin-x64": "0.35.5",+ "@img/sharp-freebsd-wasm32": "0.35.5",+ "@img/sharp-libvips-darwin-arm64": "1.3.4",+ "@img/sharp-libvips-darwin-x64": "1.3.4",+ "@img/sharp-libvips-linux-arm": "1.3.4",+ "@img/sharp-libvips-linux-arm64": "1.3.4",+ "@img/sharp-libvips-linux-ppc64": "1.3.4",+ "@img/sharp-libvips-linux-riscv64": "1.3.4",+ "@img/sharp-libvips-linux-s390x": "1.3.4",+ "@img/sharp-libvips-linux-x64": "1.3.4",+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.4",+ "@img/sharp-libvips-linuxmusl-x64": "1.3.4",+ "@img/sharp-linux-arm": "0.35.5",+ "@img/sharp-linux-arm64": "0.35.5",+ "@img/sharp-linux-ppc64": "0.35.5",+ "@img/sharp-linux-riscv64": "0.35.5",+ "@img/sharp-linux-s390x": "0.35.5",+ "@img/sharp-linux-x64": "0.35.5",+ "@img/sharp-linuxmusl-arm64": "0.35.5",+ "@img/sharp-linuxmusl-x64": "0.35.5",+ "@img/sharp-webcontainers-wasm32": "0.35.5",+ "@img/sharp-win32-arm64": "0.35.5",+ "@img/sharp-win32-ia32": "0.35.5",+ "@img/sharp-win32-x64": "0.35.5"+ },+ "peerDependenciesMeta": {+ "@types/node": {+ "optional": true+ }+ }+ },+ "node_modules/tslib": {+ "version": "2.8.1",+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",+ "optional": true+ },+ "node_modules/uniq": {+ "version": "1.0.1",+ "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",+ "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA=="+ }+ }+}
tools/hero-optimizer/package.jsonadded+18@@ -0,0 +1,18 @@+{+ "dependencies": {+ "@gltf-transform/core": "^4.5.1",+ "@gltf-transform/extensions": "^4.5.1",+ "@gltf-transform/functions": "^4.5.1",+ "@img/sharp-libvips-linux-x64": "^1.3.4",+ "@img/sharp-linux-x64": "^0.35.5",+ "draco3dgltf": "^1.5.7",+ "gltf-validator": "^2.0.0-dev.3.10",+ "meshoptimizer": "^1.3.0"+ },+ "name": "electronic-load-hero-optimizer",+ "private": true,+ "type": "module",+ "engines": {+ "node": ">=22"+ }+}