@the-inclusionist/engine 9.0.0 → 11.0.0
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.
- package/README.md +120 -78
- package/app/css/style.css +761 -377
- package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
- package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
- package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
- package/app/public/vendor/fonts.css +36 -84
- package/dist-pkg/boot/create-game.d.ts +499 -219
- package/dist-pkg/boot/create-game.js +3944 -562
- package/dist-pkg/core/a11y-sr.d.ts +25 -3
- package/dist-pkg/core/a11y-sr.js +38 -19
- package/dist-pkg/core/accessible-label.d.ts +17 -0
- package/dist-pkg/core/accessible-label.js +37 -0
- package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
- package/dist-pkg/core/accommodation-subjects.js +32 -0
- package/dist-pkg/core/accommodations.d.ts +125 -0
- package/dist-pkg/core/accommodations.js +195 -0
- package/dist-pkg/core/actions.d.ts +108 -55
- package/dist-pkg/core/actions.js +122 -71
- package/dist-pkg/core/calm-mode.d.ts +31 -0
- package/dist-pkg/core/calm-mode.js +47 -0
- package/dist-pkg/core/camera-cycle.d.ts +15 -0
- package/dist-pkg/core/camera-cycle.js +7 -0
- package/dist-pkg/core/caption-duration.d.ts +15 -0
- package/dist-pkg/core/caption-duration.js +19 -0
- package/dist-pkg/core/cartridge-problems.d.ts +34 -0
- package/dist-pkg/core/cartridge-problems.js +53 -0
- package/dist-pkg/core/constants.d.ts +0 -54
- package/dist-pkg/core/constants.js +9 -76
- package/dist-pkg/core/contract.d.ts +142 -164
- package/dist-pkg/core/contract.js +222 -208
- package/dist-pkg/core/dom-query.d.ts +4 -4
- package/dist-pkg/core/dom-query.js +12 -20
- package/dist-pkg/core/entity.d.ts +62 -77
- package/dist-pkg/core/entity.js +18 -32
- package/dist-pkg/core/escape-html.d.ts +9 -10
- package/dist-pkg/core/escape-html.js +16 -20
- package/dist-pkg/core/flash-threshold.d.ts +17 -0
- package/dist-pkg/core/flash-threshold.js +113 -0
- package/dist-pkg/core/game-speed.d.ts +11 -0
- package/dist-pkg/core/game-speed.js +16 -0
- package/dist-pkg/core/genres.d.ts +20 -0
- package/dist-pkg/core/genres.js +44 -0
- package/dist-pkg/core/i18n.d.ts +71 -60
- package/dist-pkg/core/i18n.js +186 -200
- package/dist-pkg/core/loop.d.ts +17 -6
- package/dist-pkg/core/loop.js +26 -26
- package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
- package/dist-pkg/core/pause-icon-catalogue.js +54 -0
- package/dist-pkg/core/ring.d.ts +17 -0
- package/dist-pkg/core/ring.js +29 -0
- package/dist-pkg/core/rng.d.ts +7 -12
- package/dist-pkg/core/rng.js +23 -53
- package/dist-pkg/core/route.d.ts +26 -26
- package/dist-pkg/core/route.js +126 -121
- package/dist-pkg/core/scenes.d.ts +37 -40
- package/dist-pkg/core/scenes.js +41 -43
- package/dist-pkg/core/screens.d.ts +4 -4
- package/dist-pkg/core/screens.js +11 -16
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/core/setting-defaults.d.ts +61 -0
- package/dist-pkg/core/setting-defaults.js +66 -0
- package/dist-pkg/core/speech-rate.d.ts +29 -0
- package/dist-pkg/core/speech-rate.js +47 -0
- package/dist-pkg/core/state.d.ts +118 -118
- package/dist-pkg/core/state.js +322 -297
- package/dist-pkg/core/visual-cycles.d.ts +30 -0
- package/dist-pkg/core/visual-cycles.js +52 -0
- package/dist-pkg/core/visual-state.d.ts +13 -0
- package/dist-pkg/core/visual-state.js +6 -0
- package/dist-pkg/educational/activities-registry.d.ts +1 -1
- package/dist-pkg/educational/activities-registry.js +9 -8
- package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
- package/dist-pkg/educational/adaptive-engine.js +17 -17
- package/dist-pkg/educational/segment-bar.d.ts +12 -12
- package/dist-pkg/educational/segment-bar.js +9 -9
- package/dist-pkg/i18n/en.js +324 -223
- package/dist-pkg/i18n/es.js +323 -223
- package/dist-pkg/i18n/pt.js +348 -226
- package/dist-pkg/input/default-bindings.d.ts +37 -38
- package/dist-pkg/input/default-bindings.js +127 -144
- package/dist-pkg/input/devices.d.ts +7 -7
- package/dist-pkg/input/devices.js +17 -16
- package/dist-pkg/input/edges.d.ts +23 -32
- package/dist-pkg/input/edges.js +23 -28
- package/dist-pkg/input/empathy-filter.d.ts +22 -0
- package/dist-pkg/input/empathy-filter.js +34 -0
- package/dist-pkg/input/face-map.d.ts +96 -0
- package/dist-pkg/input/face-map.js +255 -0
- package/dist-pkg/input/face-signals.d.ts +40 -0
- package/dist-pkg/input/face-signals.js +48 -0
- package/dist-pkg/input/gamepad.d.ts +195 -145
- package/dist-pkg/input/gamepad.js +383 -556
- package/dist-pkg/input/gaze-cycle.d.ts +64 -0
- package/dist-pkg/input/gaze-cycle.js +133 -0
- package/dist-pkg/input/gaze-relative.d.ts +68 -0
- package/dist-pkg/input/gaze-relative.js +142 -0
- package/dist-pkg/input/hand-map.d.ts +28 -0
- package/dist-pkg/input/hand-map.js +142 -0
- package/dist-pkg/input/input-cooldown.d.ts +17 -0
- package/dist-pkg/input/input-cooldown.js +39 -0
- package/dist-pkg/input/key-default.d.ts +30 -0
- package/dist-pkg/input/key-default.js +60 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
- package/dist-pkg/input/keyboard-runtime.js +23 -27
- package/dist-pkg/input/keyboard.d.ts +68 -63
- package/dist-pkg/input/keyboard.js +83 -105
- package/dist-pkg/input/keydown.d.ts +123 -137
- package/dist-pkg/input/keydown.js +284 -289
- package/dist-pkg/input/latch-edge.d.ts +33 -21
- package/dist-pkg/input/latch-edge.js +34 -35
- package/dist-pkg/input/latch-scope.d.ts +51 -50
- package/dist-pkg/input/latch-scope.js +61 -82
- package/dist-pkg/input/latch-store.d.ts +26 -30
- package/dist-pkg/input/latch-store.js +42 -50
- package/dist-pkg/input/latch-sync.d.ts +29 -29
- package/dist-pkg/input/latch-sync.js +25 -25
- package/dist-pkg/input/latch.d.ts +14 -17
- package/dist-pkg/input/latch.js +29 -37
- package/dist-pkg/input/pad-defaults.d.ts +13 -16
- package/dist-pkg/input/pad-defaults.js +21 -28
- package/dist-pkg/input/pad-reading.d.ts +76 -0
- package/dist-pkg/input/pad-reading.js +169 -0
- package/dist-pkg/input/pad-wizard.d.ts +99 -0
- package/dist-pkg/input/pad-wizard.js +256 -0
- package/dist-pkg/input/pointer-space.d.ts +19 -20
- package/dist-pkg/input/pointer-space.js +27 -32
- package/dist-pkg/input/pointer.d.ts +39 -40
- package/dist-pkg/input/pointer.js +42 -45
- package/dist-pkg/input/state.d.ts +101 -89
- package/dist-pkg/input/state.js +54 -134
- package/dist-pkg/input/switch-scan.d.ts +59 -0
- package/dist-pkg/input/switch-scan.js +67 -0
- package/dist-pkg/input/synthetic-source.d.ts +42 -0
- package/dist-pkg/input/synthetic-source.js +57 -0
- package/dist-pkg/input/touch-bindings.d.ts +127 -116
- package/dist-pkg/input/touch-bindings.js +158 -173
- package/dist-pkg/input/touch.d.ts +147 -72
- package/dist-pkg/input/touch.js +362 -126
- package/dist-pkg/input/transport-in-use.d.ts +107 -0
- package/dist-pkg/input/transport-in-use.js +130 -0
- package/dist-pkg/input/transports.d.ts +90 -117
- package/dist-pkg/input/transports.js +104 -106
- package/dist-pkg/input/virtual-controller.d.ts +82 -0
- package/dist-pkg/input/virtual-controller.js +69 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
- package/dist-pkg/input/vocabulary-migration.js +80 -79
- package/dist-pkg/input/voice-map.d.ts +59 -0
- package/dist-pkg/input/voice-map.js +123 -0
- package/dist-pkg/platform/audio-ambient.d.ts +13 -2
- package/dist-pkg/platform/audio-ambient.js +14 -14
- package/dist-pkg/platform/audio-earcons.d.ts +20 -19
- package/dist-pkg/platform/audio-earcons.js +51 -42
- package/dist-pkg/platform/audio-jingles.js +9 -10
- package/dist-pkg/platform/audio-mixer.d.ts +14 -2
- package/dist-pkg/platform/audio-mixer.js +31 -39
- package/dist-pkg/platform/audio-sonar.d.ts +49 -152
- package/dist-pkg/platform/audio-sonar.js +124 -302
- package/dist-pkg/platform/audio.d.ts +62 -19
- package/dist-pkg/platform/audio.js +193 -168
- package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
- package/dist-pkg/platform/choose-by-voice.js +157 -0
- package/dist-pkg/platform/flash-sampler.d.ts +19 -0
- package/dist-pkg/platform/flash-sampler.js +79 -0
- package/dist-pkg/platform/font-library.d.ts +77 -0
- package/dist-pkg/platform/font-library.js +98 -0
- package/dist-pkg/platform/font-library.json +721 -0
- package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
- package/dist-pkg/platform/heavy-catalogue.js +256 -0
- package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
- package/dist-pkg/platform/heavy-mirror.js +73 -0
- package/dist-pkg/platform/heavy.d.ts +136 -0
- package/dist-pkg/platform/heavy.js +324 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
- package/dist-pkg/platform/interruptible-speech.js +77 -54
- package/dist-pkg/platform/kokoro-port.d.ts +27 -0
- package/dist-pkg/platform/kokoro-port.js +50 -0
- package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
- package/dist-pkg/platform/kokoro-runtime.js +52 -0
- package/dist-pkg/platform/kokoro.d.ts +70 -0
- package/dist-pkg/platform/kokoro.js +133 -0
- package/dist-pkg/platform/listener-scope.d.ts +12 -0
- package/dist-pkg/platform/listener-scope.js +90 -0
- package/dist-pkg/platform/locale-host.d.ts +14 -0
- package/dist-pkg/platform/locale-host.js +45 -0
- package/dist-pkg/platform/microphone.d.ts +51 -0
- package/dist-pkg/platform/microphone.js +118 -0
- package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
- package/dist-pkg/platform/onnx-runtime.js +42 -0
- package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
- package/dist-pkg/platform/reading-in-worker.js +125 -0
- package/dist-pkg/platform/reading-model.d.ts +94 -0
- package/dist-pkg/platform/reading-model.js +272 -0
- package/dist-pkg/platform/reading-runtime.d.ts +24 -0
- package/dist-pkg/platform/reading-runtime.js +164 -0
- package/dist-pkg/platform/reading-worker.d.ts +41 -0
- package/dist-pkg/platform/reading-worker.js +58 -0
- package/dist-pkg/platform/reading.d.ts +80 -0
- package/dist-pkg/platform/reading.js +136 -0
- package/dist-pkg/platform/speech-recognition.d.ts +60 -0
- package/dist-pkg/platform/speech-recognition.js +104 -0
- package/dist-pkg/platform/speech.d.ts +23 -1
- package/dist-pkg/platform/speech.js +29 -18
- package/dist-pkg/platform/storage-keys.d.ts +96 -0
- package/dist-pkg/platform/storage-keys.js +106 -0
- package/dist-pkg/platform/storage.d.ts +46 -111
- package/dist-pkg/platform/storage.js +104 -169
- package/dist-pkg/platform/tts.d.ts +85 -39
- package/dist-pkg/platform/tts.js +447 -127
- package/dist-pkg/platform/vision-loop.d.ts +23 -0
- package/dist-pkg/platform/vision-loop.js +56 -0
- package/dist-pkg/platform/vision.d.ts +132 -0
- package/dist-pkg/platform/vision.js +117 -0
- package/dist-pkg/platform/voice-listener.d.ts +40 -0
- package/dist-pkg/platform/voice-listener.js +88 -0
- package/dist-pkg/platform/voice-plan.d.ts +15 -98
- package/dist-pkg/platform/voice-plan.js +56 -143
- package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
- package/dist-pkg/platform/vosk-runtime.js +151 -0
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/canvas.d.ts +13 -7
- package/dist-pkg/render/canvas.js +13 -13
- package/dist-pkg/render/crt.d.ts +48 -12
- package/dist-pkg/render/crt.js +78 -80
- package/dist-pkg/render/cvd-matrices.d.ts +22 -18
- package/dist-pkg/render/cvd-matrices.js +37 -38
- package/dist-pkg/render/hc-role-data.d.ts +7 -7
- package/dist-pkg/render/hc-role-data.js +14 -14
- package/dist-pkg/render/high-contrast.d.ts +67 -56
- package/dist-pkg/render/high-contrast.js +226 -217
- package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
- package/dist-pkg/render/low-vision-drawing.js +46 -0
- package/dist-pkg/render/lq-filter.d.ts +32 -20
- package/dist-pkg/render/lq-filter.js +59 -65
- package/dist-pkg/render/port.d.ts +86 -88
- package/dist-pkg/render/port.js +17 -23
- package/dist-pkg/render/screen-pipeline.d.ts +42 -42
- package/dist-pkg/render/screen-pipeline.js +80 -87
- package/dist-pkg/render/sprite-fx.d.ts +2 -1
- package/dist-pkg/render/sprite-fx.js +16 -14
- package/dist-pkg/render/viewports.d.ts +20 -15
- package/dist-pkg/render/viewports.js +83 -114
- package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
- package/dist-pkg/render/viz-axes-labels.js +88 -0
- package/dist-pkg/render/viz-axes.d.ts +89 -86
- package/dist-pkg/render/viz-axes.js +128 -116
- package/dist-pkg/render/viz-modes.d.ts +28 -29
- package/dist-pkg/render/viz-modes.js +40 -45
- package/dist-pkg/render/viz-refusal.d.ts +32 -0
- package/dist-pkg/render/viz-refusal.js +57 -0
- package/dist-pkg/render/viz-setters.d.ts +104 -66
- package/dist-pkg/render/viz-setters.js +182 -191
- package/dist-pkg/ui/aac-sets.d.ts +45 -0
- package/dist-pkg/ui/aac-sets.js +41 -0
- package/dist-pkg/ui/audio-choices.d.ts +68 -0
- package/dist-pkg/ui/audio-choices.js +98 -0
- package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
- package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
- package/dist-pkg/ui/camera-control.d.ts +53 -0
- package/dist-pkg/ui/camera-control.js +48 -0
- package/dist-pkg/ui/changed-mark.d.ts +9 -8
- package/dist-pkg/ui/changed-mark.js +22 -53
- package/dist-pkg/ui/control-choices.d.ts +37 -0
- package/dist-pkg/ui/control-choices.js +84 -0
- package/dist-pkg/ui/debug-panel.d.ts +59 -43
- package/dist-pkg/ui/debug-panel.js +68 -69
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/dom.d.ts +10 -14
- package/dist-pkg/ui/dom.js +10 -47
- package/dist-pkg/ui/drawing-problems.d.ts +25 -0
- package/dist-pkg/ui/drawing-problems.js +94 -0
- package/dist-pkg/ui/eye-control.d.ts +36 -0
- package/dist-pkg/ui/eye-control.js +178 -0
- package/dist-pkg/ui/face-control.d.ts +25 -0
- package/dist-pkg/ui/face-control.js +183 -0
- package/dist-pkg/ui/focus-trap.d.ts +39 -49
- package/dist-pkg/ui/focus-trap.js +56 -65
- package/dist-pkg/ui/fonts.d.ts +157 -68
- package/dist-pkg/ui/fonts.js +305 -115
- package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
- package/dist-pkg/ui/footer-scroll-driver.js +201 -0
- package/dist-pkg/ui/footer-scroll.d.ts +38 -0
- package/dist-pkg/ui/footer-scroll.js +55 -0
- package/dist-pkg/ui/game-options.d.ts +47 -0
- package/dist-pkg/ui/game-options.js +158 -0
- package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
- package/dist-pkg/ui/gaze-overlay.js +165 -0
- package/dist-pkg/ui/hand-control.d.ts +25 -0
- package/dist-pkg/ui/hand-control.js +143 -0
- package/dist-pkg/ui/help-panel.d.ts +87 -0
- package/dist-pkg/ui/help-panel.js +242 -0
- package/dist-pkg/ui/hud-bands.d.ts +62 -0
- package/dist-pkg/ui/hud-bands.js +146 -0
- package/dist-pkg/ui/hud-row.d.ts +34 -0
- package/dist-pkg/ui/hud-row.js +80 -0
- package/dist-pkg/ui/hud.d.ts +73 -73
- package/dist-pkg/ui/hud.js +94 -98
- package/dist-pkg/ui/item-announcement.d.ts +13 -12
- package/dist-pkg/ui/item-announcement.js +25 -26
- package/dist-pkg/ui/layout.d.ts +103 -28
- package/dist-pkg/ui/layout.js +117 -99
- package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
- package/dist-pkg/ui/libras-avatar-clip.js +86 -0
- package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
- package/dist-pkg/ui/libras-avatar-load.js +134 -0
- package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
- package/dist-pkg/ui/libras-avatar-plan.js +211 -0
- package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
- package/dist-pkg/ui/libras-avatar-player.js +226 -0
- package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
- package/dist-pkg/ui/libras-avatar-stage.js +208 -0
- package/dist-pkg/ui/libras-glosses.d.ts +28 -0
- package/dist-pkg/ui/libras-glosses.js +161 -0
- package/dist-pkg/ui/locale-flags.d.ts +16 -0
- package/dist-pkg/ui/locale-flags.js +30 -0
- package/dist-pkg/ui/loop-crash.d.ts +17 -17
- package/dist-pkg/ui/loop-crash.js +33 -62
- package/dist-pkg/ui/menu-intent.d.ts +61 -0
- package/dist-pkg/ui/menu-intent.js +88 -0
- package/dist-pkg/ui/menu-items.d.ts +20 -0
- package/dist-pkg/ui/menu-items.js +51 -0
- package/dist-pkg/ui/menu-nav.d.ts +98 -92
- package/dist-pkg/ui/menu-nav.js +398 -286
- package/dist-pkg/ui/mobility-choices.d.ts +26 -0
- package/dist-pkg/ui/mobility-choices.js +41 -0
- package/dist-pkg/ui/motion-choices.d.ts +31 -0
- package/dist-pkg/ui/motion-choices.js +68 -0
- package/dist-pkg/ui/motion-scene.d.ts +24 -19
- package/dist-pkg/ui/motion-scene.js +29 -61
- package/dist-pkg/ui/mount-panel.d.ts +81 -0
- package/dist-pkg/ui/mount-panel.js +61 -0
- package/dist-pkg/ui/panel-shell.d.ts +65 -31
- package/dist-pkg/ui/panel-shell.js +92 -66
- package/dist-pkg/ui/panel-widgets.d.ts +150 -0
- package/dist-pkg/ui/panel-widgets.js +294 -0
- package/dist-pkg/ui/pause-buttons.d.ts +35 -0
- package/dist-pkg/ui/pause-buttons.js +66 -0
- package/dist-pkg/ui/pause-icons.d.ts +261 -347
- package/dist-pkg/ui/pause-icons.js +671 -601
- package/dist-pkg/ui/pause-markup.d.ts +86 -0
- package/dist-pkg/ui/pause-markup.js +125 -0
- package/dist-pkg/ui/reach-notice.d.ts +22 -23
- package/dist-pkg/ui/reach-notice.js +55 -58
- package/dist-pkg/ui/scan-overlay.d.ts +23 -0
- package/dist-pkg/ui/scan-overlay.js +50 -0
- package/dist-pkg/ui/screen-text.d.ts +25 -0
- package/dist-pkg/ui/screen-text.js +152 -0
- package/dist-pkg/ui/session-clock.d.ts +32 -0
- package/dist-pkg/ui/session-clock.js +67 -0
- package/dist-pkg/ui/settings-aac.d.ts +70 -0
- package/dist-pkg/ui/settings-aac.js +208 -0
- package/dist-pkg/ui/settings-audio.d.ts +97 -114
- package/dist-pkg/ui/settings-audio.js +493 -425
- package/dist-pkg/ui/settings-controls.d.ts +53 -96
- package/dist-pkg/ui/settings-controls.js +143 -215
- package/dist-pkg/ui/settings-empathy.d.ts +39 -30
- package/dist-pkg/ui/settings-empathy.js +53 -60
- package/dist-pkg/ui/settings-mobility.d.ts +192 -0
- package/dist-pkg/ui/settings-mobility.js +332 -0
- package/dist-pkg/ui/settings-motion.d.ts +91 -70
- package/dist-pkg/ui/settings-motion.js +287 -198
- package/dist-pkg/ui/settings-panel.d.ts +58 -45
- package/dist-pkg/ui/settings-panel.js +189 -94
- package/dist-pkg/ui/settings-typo.d.ts +29 -78
- package/dist-pkg/ui/settings-typo.js +158 -129
- package/dist-pkg/ui/settings-visual.d.ts +29 -87
- package/dist-pkg/ui/settings-visual.js +240 -193
- package/dist-pkg/ui/shell.d.ts +112 -135
- package/dist-pkg/ui/shell.js +148 -217
- package/dist-pkg/ui/simulation-list.d.ts +27 -0
- package/dist-pkg/ui/simulation-list.js +76 -0
- package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
- package/dist-pkg/ui/simulation-over-the-world.js +131 -0
- package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
- package/dist-pkg/ui/simulation-refusal.js +8 -56
- package/dist-pkg/ui/switchable-control.d.ts +11 -0
- package/dist-pkg/ui/switchable-control.js +19 -0
- package/dist-pkg/ui/title.d.ts +3 -12
- package/dist-pkg/ui/title.js +49 -18
- package/dist-pkg/ui/top-band.d.ts +26 -0
- package/dist-pkg/ui/top-band.js +96 -0
- package/dist-pkg/ui/typo-choices.d.ts +71 -0
- package/dist-pkg/ui/typo-choices.js +85 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
- package/dist-pkg/ui/visual-axes-panel.js +12 -94
- package/dist-pkg/ui/visual-choices.d.ts +77 -0
- package/dist-pkg/ui/visual-choices.js +107 -0
- package/dist-pkg/ui/vlibras.d.ts +77 -10
- package/dist-pkg/ui/vlibras.js +130 -81
- package/dist-pkg/ui/voice-control.d.ts +68 -0
- package/dist-pkg/ui/voice-control.js +276 -0
- package/dist-pkg/ui/voice-settings.d.ts +95 -0
- package/dist-pkg/ui/voice-settings.js +352 -0
- package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
- package/dist-pkg/ui/where-the-child-is.js +70 -0
- package/docs/CREDITS.md +300 -44
- package/docs/LICENSES.md +189 -145
- package/package.json +51 -27
- package/scripts/check-cartridge.mjs +78 -0
- package/scripts/game-build.d.mts +25 -0
- package/scripts/game-build.mjs +144 -0
- package/scripts/heavy-into-the-delivery.mjs +388 -0
- package/scripts/libras-avatar.json +680 -0
- package/scripts/libras-avatar.mjs +246 -0
- package/scripts/libras-glosses/gloss.py +95 -0
- package/scripts/libras-glosses/pyproject.toml +32 -0
- package/scripts/libras-glosses/uv.lock +781 -0
- package/scripts/libras-glosses.mjs +351 -0
- package/scripts/licences/Apache-2.0.txt +176 -0
- package/scripts/licences/GPL-3.0.txt +674 -0
- package/scripts/licences/MIT.txt +17 -0
- package/scripts/licences/OFL-1.1.txt +86 -0
- package/scripts/licences/UFL-1.0.txt +96 -0
- package/scripts/licences/fonts.mjs +389 -0
- package/scripts/licences/third-party.mjs +301 -0
- package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.woff2 +0 -0
- package/app/public/vendor/fonts/lato-400.woff2 +0 -0
- package/app/public/vendor/fonts/lato-700.woff2 +0 -0
- package/app/public/vendor/fonts/literata-400.woff2 +0 -0
- package/app/public/vendor/fonts/literata-700.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
- package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
- package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
- package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/dist-pkg/core/anel.d.ts +0 -17
- package/dist-pkg/core/anel.js +0 -31
- package/dist-pkg/core/collision.d.ts +0 -21
- package/dist-pkg/core/collision.js +0 -62
- package/dist-pkg/core/layers.d.ts +0 -63
- package/dist-pkg/core/layers.js +0 -95
- package/dist-pkg/core/letter-grid.d.ts +0 -55
- package/dist-pkg/core/letter-grid.js +0 -116
- package/dist-pkg/core/password.d.ts +0 -34
- package/dist-pkg/core/password.js +0 -205
- package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
- package/dist-pkg/core/rotulo-acessivel.js +0 -41
- package/dist-pkg/core/run-state.d.ts +0 -115
- package/dist-pkg/core/run-state.js +0 -40
- package/dist-pkg/core/tiles.d.ts +0 -12
- package/dist-pkg/core/tiles.js +0 -61
- package/dist-pkg/core/world.d.ts +0 -4
- package/dist-pkg/core/world.js +0 -58
- package/dist-pkg/input/origem-sintetica.d.ts +0 -44
- package/dist-pkg/input/origem-sintetica.js +0 -60
- package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
- package/dist-pkg/input/transporte-em-uso.js +0 -130
- package/dist-pkg/platform/audio-nav.d.ts +0 -51
- package/dist-pkg/platform/audio-nav.js +0 -99
- package/dist-pkg/platform/guide-intensity.d.ts +0 -40
- package/dist-pkg/platform/guide-intensity.js +0 -73
- package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
- package/dist-pkg/platform/pesados-catalogo.js +0 -177
- package/dist-pkg/platform/pesados.d.ts +0 -31
- package/dist-pkg/platform/pesados.js +0 -75
- package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
- package/dist-pkg/platform/vozes-prontas.js +0 -61
- package/dist-pkg/render/camera.d.ts +0 -58
- package/dist-pkg/render/camera.js +0 -105
- package/dist-pkg/render/cenario-data.d.ts +0 -127
- package/dist-pkg/render/cenario-data.js +0 -145
- package/dist-pkg/render/city-tex.d.ts +0 -63
- package/dist-pkg/render/city-tex.js +0 -228
- package/dist-pkg/render/city-tiles.d.ts +0 -11
- package/dist-pkg/render/city-tiles.js +0 -140
- package/dist-pkg/render/draw.d.ts +0 -149
- package/dist-pkg/render/draw.js +0 -231
- package/dist-pkg/render/fx.d.ts +0 -63
- package/dist-pkg/render/fx.js +0 -123
- package/dist-pkg/render/minimap.d.ts +0 -11
- package/dist-pkg/render/minimap.js +0 -94
- package/dist-pkg/render/parallax.d.ts +0 -85
- package/dist-pkg/render/parallax.js +0 -158
- package/dist-pkg/render/player-anim.d.ts +0 -71
- package/dist-pkg/render/player-anim.js +0 -152
- package/dist-pkg/render/recycling-tex.d.ts +0 -48
- package/dist-pkg/render/recycling-tex.js +0 -164
- package/dist-pkg/render/scene-city.d.ts +0 -77
- package/dist-pkg/render/scene-city.js +0 -181
- package/dist-pkg/render/scene-parallax.d.ts +0 -72
- package/dist-pkg/render/scene-parallax.js +0 -426
- package/dist-pkg/render/scene-sky.d.ts +0 -126
- package/dist-pkg/render/scene-sky.js +0 -295
- package/dist-pkg/render/set-cenario.d.ts +0 -54
- package/dist-pkg/render/set-cenario.js +0 -103
- package/dist-pkg/render/textures.d.ts +0 -75
- package/dist-pkg/render/textures.js +0 -240
- package/dist-pkg/render/title-scene.d.ts +0 -46
- package/dist-pkg/render/title-scene.js +0 -75
- package/dist-pkg/render/weather.d.ts +0 -96
- package/dist-pkg/render/weather.js +0 -171
- package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
- package/dist-pkg/render/wheelchair-sprites.js +0 -69
- package/dist-pkg/render/world-tex.d.ts +0 -18
- package/dist-pkg/render/world-tex.js +0 -87
- package/dist-pkg/ui/activities-menu.d.ts +0 -258
- package/dist-pkg/ui/activities-menu.js +0 -648
- package/dist-pkg/ui/caa-sets.d.ts +0 -39
- package/dist-pkg/ui/caa-sets.js +0 -65
- package/dist-pkg/ui/latch-refusal.d.ts +0 -32
- package/dist-pkg/ui/latch-refusal.js +0 -60
- package/dist-pkg/ui/map-hub.d.ts +0 -56
- package/dist-pkg/ui/map-hub.js +0 -138
- package/dist-pkg/ui/settings-caa.d.ts +0 -45
- package/dist-pkg/ui/settings-caa.js +0 -137
- package/dist-pkg/ui/settings-motor.d.ts +0 -175
- package/dist-pkg/ui/settings-motor.js +0 -342
- package/dist-pkg/ui/webcam.d.ts +0 -7
- package/dist-pkg/ui/webcam.js +0 -93
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
// THE CARTRIDGE CHECKER — `inclusionist-check-cartridge [built entry]` (ADR-0253). Default entry: `dist-lib/cartridge.js`, where
|
|
4
|
+
// the engine's build (`@the-inclusionist/engine/build`, `vite build --mode cartridge`) puts it.
|
|
5
|
+
//
|
|
6
|
+
// It IMPORTS the built cartridge and runs on what it exports the SAME list `createGame` and `mount()` refuse a cartridge with —
|
|
7
|
+
// `cartridgeRefusals`, from the engine this script ships in. A cartridge that compiles and breaks the contract is refused here,
|
|
8
|
+
// in the game's CI, instead of in the platform the day it is installed. One line per problem, in the `problems` shape: the subject
|
|
9
|
+
// by name, and the fix.
|
|
10
|
+
//
|
|
11
|
+
// ⚠️ WHAT IT READS IS ADR-0139 §2's `Cartridge`, as the entry's DEFAULT export: `{ slug, declaration, hooks, create }`. The
|
|
12
|
+
// declaration and the hooks are read at import, before `create(ctx)` runs, because that is when `createGame` reads them too.
|
|
13
|
+
// ⚠️ AND IT IMPORTS IN NODE, WITH NO PAGE. A cartridge runs nothing until `create(ctx)` (ADR-0139 §2): one whose import needs a
|
|
14
|
+
// `document` would already be touching the platform's page when it is merely installed, and the import's error is the line.
|
|
15
|
+
//
|
|
16
|
+
// Exit codes: 0 the contract holds · 1 the cartridge is refused (the lines say why) · 2 this engine was never built (`dist-pkg/`).
|
|
17
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
18
|
+
import { relative, resolve, sep } from 'node:path';
|
|
19
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
20
|
+
|
|
21
|
+
/** Where the engine's build writes the cartridge — `CARTRIDGE_DIR/CARTRIDGE_FILE` of `game-build.mjs`. */
|
|
22
|
+
export const DEFAULT_ENTRY = 'dist-lib/cartridge.js';
|
|
23
|
+
|
|
24
|
+
/** The compiled composition root of the package this script ships in, which owns the refusals. */
|
|
25
|
+
export const REFUSALS_MODULE = new URL('../dist-pkg/boot/create-game.js', import.meta.url);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The problems of a built cartridge, EMPTY when it holds. `refusals` is the engine's `cartridgeRefusals`.
|
|
29
|
+
* The four shape lines come first because without them there is nothing to hand the engine's list.
|
|
30
|
+
*/
|
|
31
|
+
export async function checkCartridge(entryPath, refusals) {
|
|
32
|
+
const shown = shownPath(entryPath);
|
|
33
|
+
if (!existsSync(entryPath)) {
|
|
34
|
+
return [`${shown}: missing - this game does not build its cartridge with the engine's build: wrap vite.config in defineGameBuild from @the-inclusionist/engine/build and run \`vite build --mode cartridge\` (ADR-0253)`];
|
|
35
|
+
}
|
|
36
|
+
let mod;
|
|
37
|
+
try {
|
|
38
|
+
mod = await import(pathToFileURL(entryPath).href);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return [`importing the cartridge threw: ${messageOf(e)} - a cartridge runs nothing until create(ctx) (ADR-0139 §2), so importing it must need no page`];
|
|
41
|
+
}
|
|
42
|
+
const cartridge = mod.default;
|
|
43
|
+
if (!cartridge || typeof cartridge !== 'object') {
|
|
44
|
+
return ['default export: missing - the built entry exports the cartridge as its default, { slug, declaration, hooks, create } (ADR-0139 §2)'];
|
|
45
|
+
}
|
|
46
|
+
const shape = [];
|
|
47
|
+
if (typeof cartridge.slug !== 'string' || !cartridge.slug.trim()) shape.push('slug: missing - the repository and package name, one word (ADR-0082 §1)');
|
|
48
|
+
if (typeof cartridge.create !== 'function') shape.push('create: must be a function - the shell calls create(ctx) to start the game, and nothing runs before it (ADR-0139 §2)');
|
|
49
|
+
try {
|
|
50
|
+
return [...shape, ...refusals(cartridge.declaration, cartridge.hooks)];
|
|
51
|
+
} catch (e) {
|
|
52
|
+
return [...shape, `the declaration threw while the engine checked it: ${messageOf(e)} - createGame and mount read it at boot, before create(ctx) runs`];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** A path as the reader typed it: relative to where the check runs, with forward slashes on every system. */
|
|
57
|
+
const shownPath = (p) => (relative(process.cwd(), p) || p).split(sep).join('/');
|
|
58
|
+
|
|
59
|
+
const messageOf = (e) => (e instanceof Error ? e.message : String(e));
|
|
60
|
+
|
|
61
|
+
// Run as a program (directly, or through the `inclusionist-check-cartridge` shim, which may be a symlink): compare real paths.
|
|
62
|
+
const run = (() => { try { return realpathSync(process.argv[1] ?? '') === realpathSync(fileURLToPath(import.meta.url)); } catch { return false; } })();
|
|
63
|
+
if (run) {
|
|
64
|
+
if (!existsSync(fileURLToPath(REFUSALS_MODULE))) {
|
|
65
|
+
console.error('dist-pkg/boot/create-game.js is missing beside this script: in the engine repository, run `npm run build:pkg` first');
|
|
66
|
+
process.exit(2);
|
|
67
|
+
}
|
|
68
|
+
const { cartridgeRefusals } = await import(REFUSALS_MODULE.href);
|
|
69
|
+
const entry = resolve(process.argv[2] ?? DEFAULT_ENTRY);
|
|
70
|
+
const problems = await checkCartridge(entry, cartridgeRefusals);
|
|
71
|
+
const shown = shownPath(entry);
|
|
72
|
+
if (problems.length) {
|
|
73
|
+
console.error(`✗ cartridge ${shown}: ${problems.length} problem(s) — createGame and mount would refuse it (ADR-0253):`);
|
|
74
|
+
for (const p of problems) console.error(` · ${p}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
console.log(`✓ cartridge ${shown}: the engine's contract holds.`);
|
|
78
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// The types of `@the-inclusionist/engine/build` (`scripts/game-build.mjs`, ADR-0253). Written by hand because the module is a
|
|
3
|
+
// build script the game's Vite loads in Node, not a module of the engine's browser code that `tsconfig.pkg.json` compiles.
|
|
4
|
+
// `vite` is named only as a TYPE: the game has it, since it is what the game builds with.
|
|
5
|
+
import type { ConfigEnv, UserConfig, UserConfigFnPromise } from 'vite';
|
|
6
|
+
|
|
7
|
+
/** The Vite mode that builds the cartridge; every other mode is the app, Vitest's `test` included. */
|
|
8
|
+
export declare const CARTRIDGE_MODE: 'cartridge';
|
|
9
|
+
/** Where the cartridge lands, relative to the game's root. */
|
|
10
|
+
export declare const CARTRIDGE_DIR: 'dist-lib';
|
|
11
|
+
/** The cartridge's module inside `CARTRIDGE_DIR`; `cartridge.d.ts` is its types. */
|
|
12
|
+
export declare const CARTRIDGE_FILE: 'cartridge.js';
|
|
13
|
+
/** The engine and the shared render libraries (ADR-0140 §4): external in the cartridge, as prefixes. */
|
|
14
|
+
export declare const CARTRIDGE_EXTERNAL: readonly RegExp[];
|
|
15
|
+
|
|
16
|
+
export interface GameBuild {
|
|
17
|
+
/** The cartridge's entry, relative to the game's root — e.g. `src/index.ts`. Its default export is the cartridge. */
|
|
18
|
+
readonly cartridge: string;
|
|
19
|
+
/** The game's Vite config for the APP (the standalone PWA), exactly as it would be written without this wrapper. */
|
|
20
|
+
readonly config?: UserConfig | ((env: ConfigEnv) => UserConfig | Promise<UserConfig>);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The one declaration a game writes: `vite build` builds its app, `vite build --mode cartridge` its cartridge. */
|
|
24
|
+
export declare function defineGameBuild(build: GameBuild): UserConfigFnPromise;
|
|
25
|
+
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// THE BUILD OF BOTH TARGETS OF A GAME — published as `@the-inclusionist/engine/build` (ADR-0253, ADR-0140 §1).
|
|
3
|
+
//
|
|
4
|
+
// ========================= WHAT A GAME WRITES =========================
|
|
5
|
+
// Its `vite.config.ts` wraps the config it already has and names its cartridge's entry — one declaration:
|
|
6
|
+
//
|
|
7
|
+
// import { defineGameBuild } from '@the-inclusionist/engine/build';
|
|
8
|
+
// export default defineGameBuild({ cartridge: 'src/index.ts', config: { root: 'app', plugins: [VitePWA({ … })], … } });
|
|
9
|
+
//
|
|
10
|
+
// · `vite build` → the APP: the game's own config, untouched — the standalone PWA with the engine bundled.
|
|
11
|
+
// · `vite build --mode cartridge` → the CARTRIDGE: `dist-lib/cartridge.js` + `dist-lib/cartridge.d.ts`, the engine and the
|
|
12
|
+
// shared render libraries external. Everything else in the game's config (plugins,
|
|
13
|
+
// `define`, `resolve`, `css`) still applies, so a plugin both targets need is written once.
|
|
14
|
+
//
|
|
15
|
+
// ========================= WHY THE ENGINE OWNS THE CARTRIDGE AND NOT THE APP =========================
|
|
16
|
+
// Measured on 2026-09-27, before this existed: five of seven games declared a `build:lib`, each differently — a mode, a second
|
|
17
|
+
// config file, an npm lifecycle variable, an environment variable, a script — and one had none. What they were all writing is
|
|
18
|
+
// the same four decisions, and each is the engine's to make, because each is about what the PLATFORM receives:
|
|
19
|
+
// 1. the engine, PixiJS and Zdog stay EXTERNAL, matched as PREFIXES — an exact string externalises the bare name and silently
|
|
20
|
+
// inlines every subpath, which is how every game imports (the 15-puzzle measured 35 kB turning into 74.5 kB);
|
|
21
|
+
// 2. no `public/`: Vite copies it into every build, and a cartridge declares no delivery (ADR-0117) — chess once shipped 7 MB;
|
|
22
|
+
// 3. no service worker: the PWA plugin is dropped, since a second worker would claim the platform's origin (ADR-0140 §1);
|
|
23
|
+
// 4. types emitted, for the one entry: a platform that cannot type the cartridge has a contract that is a comment.
|
|
24
|
+
// The APP stays the game's: its manifest, colours and precache budget are statements about THAT game (ADR-0140 §3).
|
|
25
|
+
//
|
|
26
|
+
// ⚠️ THIS FILE IMPORTS NO PACKAGE, on purpose. A Vite config is data, so nothing here needs `vite`; the types are emitted with the
|
|
27
|
+
// GAME's own `typescript`, resolved from the game's root, because a game builds with its own tools and the engine declares no
|
|
28
|
+
// build-time dependency on anyone's behalf (ADR-0119).
|
|
29
|
+
import { createRequire } from 'node:module';
|
|
30
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
31
|
+
import { join, relative, resolve, sep } from 'node:path';
|
|
32
|
+
|
|
33
|
+
/** The Vite mode that builds the cartridge. The app is every other mode, which is what keeps `vite build` and Vitest untouched. */
|
|
34
|
+
export const CARTRIDGE_MODE = 'cartridge';
|
|
35
|
+
|
|
36
|
+
/** Where the cartridge lands, relative to the game's root — one place, so the shared CI and the checker need no argument. */
|
|
37
|
+
export const CARTRIDGE_DIR = 'dist-lib';
|
|
38
|
+
|
|
39
|
+
/** The cartridge's module; its types are `cartridge.d.ts` beside it, and its stylesheet, when it has one, `cartridge.css`. */
|
|
40
|
+
export const CARTRIDGE_FILE = 'cartridge.js';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* What a cartridge never carries: the engine and the shared render libraries of ADR-0140 §4. A platform installs ONE of each for
|
|
44
|
+
* every game, and one bundled into a cartridge is a second copy of its module state — two blind-mode flags, two dictionary
|
|
45
|
+
* tables, two random streams on one page.
|
|
46
|
+
*/
|
|
47
|
+
export const CARTRIDGE_EXTERNAL = [/^@the-inclusionist\/engine(\/|$)/, /^pixi\.js(\/|$)/, /^zdog(\/|$)/];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* THE ONE DECLARATION. `cartridge` is the entry, relative to the game's root (where `package.json` is and where npm and CI run);
|
|
51
|
+
* `config` is the game's Vite config for the app, an object or a function of Vite's `env`, exactly as it was written before.
|
|
52
|
+
*/
|
|
53
|
+
export function defineGameBuild({ cartridge, config } = {}) {
|
|
54
|
+
if (typeof cartridge !== 'string' || !cartridge.trim()) {
|
|
55
|
+
throw new Error('defineGameBuild: `cartridge` must name the cartridge entry, e.g. "src/index.ts" - it is the one thing the engine cannot guess (ADR-0253)');
|
|
56
|
+
}
|
|
57
|
+
return async (env) => {
|
|
58
|
+
const app = (typeof config === 'function' ? await config(env) : config) ?? {};
|
|
59
|
+
return env.mode === CARTRIDGE_MODE ? cartridgeConfig(app, cartridge, process.cwd()) : app;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The app's config turned into the cartridge's: the game's settings, with the four decisions above laid over them. */
|
|
64
|
+
function cartridgeConfig(app, cartridge, root) {
|
|
65
|
+
const entry = resolve(root, cartridge);
|
|
66
|
+
return {
|
|
67
|
+
...app,
|
|
68
|
+
publicDir: false,
|
|
69
|
+
plugins: [...withoutServiceWorker(app.plugins), cartridgeTypes(entry, root)],
|
|
70
|
+
build: {
|
|
71
|
+
outDir: join(root, CARTRIDGE_DIR),
|
|
72
|
+
emptyOutDir: true,
|
|
73
|
+
target: 'es2022',
|
|
74
|
+
lib: { entry, formats: ['es'], fileName: () => CARTRIDGE_FILE, cssFileName: 'cartridge' },
|
|
75
|
+
rolldownOptions: { external: CARTRIDGE_EXTERNAL },
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The game's plugins minus `vite-plugin-pwa` (every plugin it registers is named `vite-plugin-pwa` or `vite-plugin-pwa:…`).
|
|
82
|
+
* Arrays are flattened, because `VitePWA()` returns one; a plugin that is still a promise is kept, since its name is unknown.
|
|
83
|
+
*/
|
|
84
|
+
function withoutServiceWorker(plugins) {
|
|
85
|
+
return [plugins ?? []].flat(Infinity).filter((p) => !(p && typeof p === 'object' && /^vite-plugin-pwa(:|$)/.test(String(p.name ?? ''))));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The plugin that writes the cartridge's types once the bundle is on disk. */
|
|
89
|
+
function cartridgeTypes(entry, root) {
|
|
90
|
+
return { name: 'inclusionist:cartridge-types', apply: 'build', writeBundle: () => emitCartridgeTypes(entry, root) };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* THE TYPES OF THE CARTRIDGE, from the game's own `tsconfig.json`, for the entry's import graph and nothing else — the tests and
|
|
95
|
+
* the standalone shell are not reached from the entry, so they are not published (a platform would be invited to call the shell).
|
|
96
|
+
*
|
|
97
|
+
* ⚠️ `.ts` SPECIFIERS ARE REWRITTEN TO `.js` IN THE EMITTED `.d.ts`. The games import `./board.ts` with the extension, and
|
|
98
|
+
* TypeScript 5.9 keeps a type-only re-export's specifier as written (measured in `game-2048`): a consumer resolving it finds no
|
|
99
|
+
* `.ts`, and the package installs cleanly with no types.
|
|
100
|
+
*/
|
|
101
|
+
function emitCartridgeTypes(entry, root) {
|
|
102
|
+
const ts = createRequire(join(root, 'package.json'))('typescript');
|
|
103
|
+
const configPath = join(root, 'tsconfig.json');
|
|
104
|
+
if (!existsSync(configPath)) throw new Error(`cartridge types: there is no tsconfig.json in ${root} - the cartridge's types are emitted with the game's own settings`);
|
|
105
|
+
const host = { getCanonicalFileName: (f) => f, getCurrentDirectory: () => root, getNewLine: () => '\n' };
|
|
106
|
+
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, {
|
|
107
|
+
...ts.sys,
|
|
108
|
+
onUnRecoverableConfigFileDiagnostic: (d) => { throw new Error(`cartridge types: ${ts.formatDiagnostics([d], host)}`); },
|
|
109
|
+
});
|
|
110
|
+
const outDir = join(root, CARTRIDGE_DIR, 'types');
|
|
111
|
+
const options = {
|
|
112
|
+
...parsed.options,
|
|
113
|
+
noEmit: false, declaration: true, emitDeclarationOnly: true, declarationMap: false, sourceMap: false,
|
|
114
|
+
inlineSourceMap: false, composite: false, incremental: false, tsBuildInfoFile: undefined, noEmitOnError: false,
|
|
115
|
+
outDir, rootDir: root,
|
|
116
|
+
};
|
|
117
|
+
const program = ts.createProgram({ rootNames: [entry], options });
|
|
118
|
+
const result = program.emit();
|
|
119
|
+
const failures = [...program.getOptionsDiagnostics(), ...result.diagnostics];
|
|
120
|
+
if (failures.length) throw new Error(`cartridge types: ${ts.formatDiagnostics(failures, host)}`);
|
|
121
|
+
|
|
122
|
+
for (const file of declarationsUnder(outDir)) {
|
|
123
|
+
const before = readFileSync(file, 'utf8');
|
|
124
|
+
const after = before.replace(/((?:from|import\()\s*['"])(\.{1,2}\/[^'"]*?)\.([cm]?)ts(['"])/g, '$1$2.$3js$4');
|
|
125
|
+
if (after !== before) writeFileSync(file, after);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const entryTypes = join(outDir, relative(root, entry)).replace(/\.[cm]?[jt]sx?$/, '.d.ts');
|
|
129
|
+
if (!existsSync(entryTypes)) throw new Error(`cartridge types: TypeScript emitted no declaration for ${relative(root, entry)}`);
|
|
130
|
+
const from = './' + relative(join(root, CARTRIDGE_DIR), entryTypes).split(sep).join('/').replace(/\.d\.ts$/, '.js');
|
|
131
|
+
const hasDefault = /\bexport\s+default\b|\bas\s+default\b/.test(readFileSync(entryTypes, 'utf8'));
|
|
132
|
+
writeFileSync(join(root, CARTRIDGE_DIR, 'cartridge.d.ts'),
|
|
133
|
+
`export * from '${from}';\n${hasDefault ? `export { default } from '${from}';\n` : ''}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Every `.d.ts` under a folder, at any depth. */
|
|
137
|
+
function declarationsUnder(dir) {
|
|
138
|
+
if (!existsSync(dir)) return [];
|
|
139
|
+
return readdirSync(dir).flatMap((name) => {
|
|
140
|
+
const path = join(dir, name);
|
|
141
|
+
if (statSync(path).isDirectory()) return declarationsUnder(path);
|
|
142
|
+
return path.endsWith('.d.ts') ? [path] : [];
|
|
143
|
+
});
|
|
144
|
+
}
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
//
|
|
4
|
+
// Puts the heavy files into a delivery (ADR-0177, issue #173): each upstream address of the download catalogue is fetched at
|
|
5
|
+
// BUILD time, checked against its pinned sha256, and written to `<destination>/heavy/<host><path>` — where the page asks for
|
|
6
|
+
// it. A file whose hash differs stops the build: nothing unchecked reaches a delivery.
|
|
7
|
+
//
|
|
8
|
+
// Usage (after `npm run build`): `npm run heavy:delivery` — builds the package, then `node scripts/heavy-into-the-delivery.mjs dist`.
|
|
9
|
+
// A cartridge, after its own build, runs the published command: `npx inclusionist-heavy dist`. The catalogue is read from the
|
|
10
|
+
// package beside this script, never from the caller's folder.
|
|
11
|
+
// ⚠️ It downloads about 300 MB from Hugging Face, jsDelivr and Google Storage: the build machine
|
|
12
|
+
// contacts them once, and the child's device never does.
|
|
13
|
+
//
|
|
14
|
+
// WHERE FROM IS A CHOICE (the Dev, 2026-09-21): `--base <address or folder>`, the variable `INCLUSIONIST_HEAVY_BASE`, or a `.env`
|
|
15
|
+
// beside the build. With a base, each file comes from the project's mirror, a school's server or a folder on this machine
|
|
16
|
+
// (`platform/heavy-mirror`); without one, from upstream. The sha256 check does not move: a base that serves other bytes writes
|
|
17
|
+
// nothing, which is why pointing elsewhere is safe and needs no trust.
|
|
18
|
+
//
|
|
19
|
+
// THE FONT LIBRARY TRAVELS THE SAME WAY (ADR-0255): `--fonts` puts the families the cartridges declare into `heavy/`, each face
|
|
20
|
+
// checked against the engine's font catalogue, each family with its licence text and notice (`licences/fonts.mjs`).
|
|
21
|
+
//
|
|
22
|
+
// WHAT THE FILES OWE TRAVELS WITH THEM (`licences/third-party.mjs`): every folder of `heavy/` that holds a file also gets its
|
|
23
|
+
// project's `LICENSE` and `NOTICE` (eSpeak NG's also a `SOURCE`), and `heavy/THIRD-PARTY-NOTICES.md` lists each project. A
|
|
24
|
+
// catalogue entry whose licence nobody recorded there is refused like a file whose sha256 differs.
|
|
25
|
+
|
|
26
|
+
import { mkdirSync, writeFileSync, readFileSync, existsSync, realpathSync } from 'node:fs';
|
|
27
|
+
import { dirname, join } from 'node:path';
|
|
28
|
+
import { createHash } from 'node:crypto';
|
|
29
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
30
|
+
import { THIRD_PARTY, groupOf, writeLicences } from './licences/third-party.mjs';
|
|
31
|
+
import { familyLicenceFiles } from './licences/fonts.mjs';
|
|
32
|
+
import { deliverLibrasGlosses, readTexts, runGlosser, setUpGlosser } from './libras-glosses.mjs';
|
|
33
|
+
import { deliverLibrasAvatar, readAvatarPins, stageChunkOf, writeAvatarList } from './libras-avatar.mjs';
|
|
34
|
+
|
|
35
|
+
/** The compiled catalogue of the package this script ships in — beside it, whatever folder the build runs from. */
|
|
36
|
+
export function moduloDoPacote() {
|
|
37
|
+
return new URL('../dist-pkg/platform/heavy.js', import.meta.url).href;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const sha256DoNode = (buf) => createHash('sha256').update(Buffer.from(buf)).digest('hex');
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* ONE FILE, FETCHED (or read from a local base), CHECKED AGAINST ITS PINNED SHA256 AND WRITTEN — or refused with the reason, and
|
|
44
|
+
* nothing written. The one rule the catalogue's files and the library's fonts go through.
|
|
45
|
+
*/
|
|
46
|
+
async function trazerVerificado(p, alvo, { source, fetchFile, readLocal, sha256 }) {
|
|
47
|
+
try {
|
|
48
|
+
let corpo;
|
|
49
|
+
if (/^https?:\/\//i.test(source)) {
|
|
50
|
+
const resp = await fetchFile(source);
|
|
51
|
+
if (!resp.ok) return { id: p.id, outcome: 'falhou', error: `HTTP ${resp.status} — ${source}` };
|
|
52
|
+
corpo = await resp.arrayBuffer();
|
|
53
|
+
} else {
|
|
54
|
+
corpo = readLocal(source);
|
|
55
|
+
}
|
|
56
|
+
const obtido = sha256(corpo);
|
|
57
|
+
if (!p.sha256 || obtido !== p.sha256) {
|
|
58
|
+
return { id: p.id, outcome: 'falhou', error: `sha256 mismatch at ${source}: expected ${p.sha256}, got ${obtido} — not written` };
|
|
59
|
+
}
|
|
60
|
+
mkdirSync(dirname(alvo), { recursive: true });
|
|
61
|
+
writeFileSync(alvo, Buffer.from(corpo));
|
|
62
|
+
return { id: p.id, outcome: 'escrito', bytes: corpo.byteLength };
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return { id: p.id, outcome: 'falhou', error: e instanceof Error ? e.message : String(e) };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* THE FONT LIBRARY'S FAMILIES A DELIVERY CARRIES (ADR-0255), from `--fonts`: each value a family or a comma-separated list of
|
|
70
|
+
* them; `all` is every family of the library, `none` nothing. A family the library does not hold STOPS the command (exit 2),
|
|
71
|
+
* naming it, instead of delivering nothing for it in silence.
|
|
72
|
+
*/
|
|
73
|
+
export function fontFamiliesOfTheDelivery(asked, library) {
|
|
74
|
+
const names = asked.flatMap((v) => v.split(',')).map((f) => f.trim()).filter(Boolean);
|
|
75
|
+
if (names.includes('all')) return Object.keys(library.families);
|
|
76
|
+
const named = [...new Set(names.filter((f) => f !== 'none'))];
|
|
77
|
+
const unknown = named.filter((f) => !library.families[f]);
|
|
78
|
+
if (unknown.length) {
|
|
79
|
+
throw new Error(`--fonts ${unknown.join(', ')}: the engine's font library has no ${unknown.length > 1 ? 'such families' : 'such family'} `
|
|
80
|
+
+ '(app/js/platform/font-library.json). Name families as the library writes them — «Press Start 2P» — or `--fonts all`');
|
|
81
|
+
}
|
|
82
|
+
return named;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* PUTS THE DECLARED FAMILIES OF THE FONT LIBRARY INTO THE DELIVERY (ADR-0255): each face is fetched (or read from a local base),
|
|
87
|
+
* checked against the sha256 the ENGINE'S catalogue pins, and written at `heavy/<host>/fonts/<folder>/<file>` — where the page
|
|
88
|
+
* asks for it. Beside each family whose every face is there, its licence text and `NOTICE.txt`, written from the delivered fonts'
|
|
89
|
+
* own `name` tables (`licences/fonts.mjs`, the same writer as the library's folders). A face refused leaves its family without a
|
|
90
|
+
* notice and the run not `ok`.
|
|
91
|
+
*/
|
|
92
|
+
export async function levarFontesParaEntrega({ destino, families, library, deliveryPath, fetch: buscar = fetch, sha256 = sha256DoNode,
|
|
93
|
+
base = '', fonteDe = (url) => url, lerLocal = (caminho) => readFileSync(caminho), licenceFiles = familyLicenceFiles }) {
|
|
94
|
+
const linhas = [];
|
|
95
|
+
for (const family of families) {
|
|
96
|
+
const entry = library.families[family];
|
|
97
|
+
let whole = true;
|
|
98
|
+
let folder = '';
|
|
99
|
+
// one file may serve two weights (a variable font declared at 400 and 700): each file once
|
|
100
|
+
const faces = entry.faces.filter((f, i) => entry.faces.findIndex((g) => g.file === f.file) === i);
|
|
101
|
+
for (const face of faces) {
|
|
102
|
+
const url = `${library.mirror}/${entry.folder}/${face.file}`;
|
|
103
|
+
const p = { id: `font:${entry.folder}:${face.file}`, sha256: face.sha256 };
|
|
104
|
+
const alvo = join(destino, deliveryPath(url));
|
|
105
|
+
folder = dirname(alvo);
|
|
106
|
+
const linha = existsSync(alvo) && sha256(readFileSync(alvo)) === face.sha256
|
|
107
|
+
? { id: p.id, outcome: 'ja-tinha' }
|
|
108
|
+
: await trazerVerificado(p, alvo, { source: fonteDe(url, base), fetchFile: buscar, readLocal: lerLocal, sha256 });
|
|
109
|
+
linhas.push(linha);
|
|
110
|
+
if (linha.outcome === 'falhou') whole = false;
|
|
111
|
+
}
|
|
112
|
+
if (!whole) continue;
|
|
113
|
+
try {
|
|
114
|
+
const owed = licenceFiles(family, entry, (file) => readFileSync(join(folder, file)));
|
|
115
|
+
for (const [name, text] of Object.entries(owed)) writeFileSync(join(folder, name), text);
|
|
116
|
+
} catch (e) {
|
|
117
|
+
linhas.push({ id: `font:${entry.folder}:licence`, outcome: 'falhou', error: e instanceof Error ? e.message : String(e) });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return { ok: linhas.every((l) => l.outcome !== 'falhou'), linhas };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Fetches, checks and writes every entry with an address, then the licence files beside them. Returns one line per entry and
|
|
125
|
+
* the licence folders written (`licences`); `ok` is false when any file — or the licences — failed.
|
|
126
|
+
* Everything is injected so a gate can run it without the network.
|
|
127
|
+
*/
|
|
128
|
+
export async function levarPesadosParaEntrega({ destino, pesados, deliveryPath, fetch: buscar = fetch, sha256 = sha256DoNode,
|
|
129
|
+
base = '', fonteDe = (url) => url, lerLocal = (caminho) => readFileSync(caminho), thirdParty = THIRD_PARTY, catalogue = [] }) {
|
|
130
|
+
const linhas = [];
|
|
131
|
+
const present = [];
|
|
132
|
+
for (const p of pesados) {
|
|
133
|
+
if (!p.url) { linhas.push({ id: p.id, outcome: 'sem-fonte' }); continue; }
|
|
134
|
+
if (!groupOf(p.id, thirdParty)) {
|
|
135
|
+
linhas.push({ id: p.id, outcome: 'falhou', error: 'no licence recorded for it in scripts/licences/third-party.mjs — not written' });
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const alvo = join(destino, deliveryPath(p.url));
|
|
139
|
+
if (existsSync(alvo) && sha256(readFileSync(alvo)) === p.sha256) {
|
|
140
|
+
linhas.push({ id: p.id, outcome: 'ja-tinha' });
|
|
141
|
+
present.push({ id: p.id, path: deliveryPath(p.url) });
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const escrito = await trazerVerificado(p, alvo, { source: fonteDe(p.url, base), fetchFile: buscar, readLocal: lerLocal, sha256 });
|
|
145
|
+
linhas.push(escrito);
|
|
146
|
+
if (escrito.outcome === 'escrito') present.push({ id: p.id, path: deliveryPath(p.url) });
|
|
147
|
+
}
|
|
148
|
+
// 📌 THE NOTICES SPEAK FOR THE WHOLE DELIVERY, not for this run: a delivery may be built by several runs (`--reading pt`, then
|
|
149
|
+
// `--kokoro`), and `THIRD-PARTY-NOTICES.md` is rewritten each time. So every catalogue file ALREADY in the delivery with its
|
|
150
|
+
// pinned bytes keeps its notice; a file whose bytes are not the pinned ones gets none from here.
|
|
151
|
+
const listed = new Set(present.map((f) => f.id));
|
|
152
|
+
for (const p of catalogue) {
|
|
153
|
+
if (listed.has(p.id) || !p.url || !p.sha256 || !groupOf(p.id, thirdParty)) continue;
|
|
154
|
+
const alvo = join(destino, deliveryPath(p.url));
|
|
155
|
+
if (existsSync(alvo) && sha256(readFileSync(alvo)) === p.sha256) present.push({ id: p.id, path: deliveryPath(p.url) });
|
|
156
|
+
}
|
|
157
|
+
let licences = [];
|
|
158
|
+
try {
|
|
159
|
+
licences = writeLicences({ destination: destino, present, groups: thirdParty });
|
|
160
|
+
} catch (e) {
|
|
161
|
+
linhas.push({ id: 'licences', outcome: 'falhou', error: e instanceof Error ? e.message : String(e) });
|
|
162
|
+
}
|
|
163
|
+
return { ok: linhas.every((l) => l.outcome !== 'falhou'), linhas, licences };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* The command's arguments, which are the game's answers (ADR-0216 §3) said to the build:
|
|
168
|
+
*
|
|
169
|
+
* · `--kokoro` for a game that declares `uses: { neuralVoice: true }` — without it Kokoro's model, voices and runtime stay out of
|
|
170
|
+
* the delivery, as they stay out of the start's download.
|
|
171
|
+
* · `--reading`, for a game that declares `uses: { reading: true }`: ALONE (or `--reading all`) it carries every language the
|
|
172
|
+
* catalogue has a reading model for — pt 378 MiB, en 162, es 310 — because the start of such a game asks for the three, and a
|
|
173
|
+
* child tries the three at once (ADR-0225 erratum, the Dev: «Negativo, baixar os três.»). `--reading <pt|en|es>`, repeatable,
|
|
174
|
+
* NARROWS to the languages named, with the same bytes as before; a language left out is a quiet 404 at the device's start and,
|
|
175
|
+
* when she reads in it, a sentence to her and a line of `problems` naming this fix. `--reading none` carries none, as no flag
|
|
176
|
+
* does. A language the catalogue has no reading model for STOPS the command (exit 2) instead of carrying nothing.
|
|
177
|
+
* · `--commands <pt|en|es>`, repeatable: the voice COMMANDS (issue #184), 31–39 MiB a language plus 3.1 MiB of runtime. No game
|
|
178
|
+
* declares this one — saying «menu» is a way into the controller, not a feature (ADR-0111). WITHOUT THE FLAG THE DELIVERY
|
|
179
|
+
* CARRIES EVERY LANGUAGE the catalogue has a command model for — pt, en and es, 108 MiB (ADR-0225 erratum, the Dev: «A entrega
|
|
180
|
+
* leva as três línguas.») — because the child can switch language mid-game and her model must already be there. The flag
|
|
181
|
+
* NARROWS: the languages named, and only those; `--commands none` carries no command model at all. A language left out is
|
|
182
|
+
* said to the child who speaks it, and named in `problems` with this fix. A language the catalogue has no command model for
|
|
183
|
+
* STOPS the command (exit 2) instead of carrying the runtime alone.
|
|
184
|
+
* · `--libras`: the Libras player deaf mode's interpreter signs with (ADR-0234, route B) — LAViD-UFPB's signs exported to one
|
|
185
|
+
* avatar and 655 clips, the whole manual alphabet among them, 32.7 MiB, into `libras/avatar/`, each checked against
|
|
186
|
+
* `scripts/libras-avatar.json` (`scripts/libras-avatar.mjs`), from the pins' `source` or from their `mirror` folder under
|
|
187
|
+
* `--base`. No game declares it: deaf mode is the person's, like speaking is, so the DELIVERY says whether it can sign. Without
|
|
188
|
+
* it the sonar in deaf mode says «signing unavailable». The same step GLOSSES the text a child can be shown
|
|
189
|
+
* (`scripts/libras-glosses.mjs`): the engine's Portuguese dictionary, always, and the game's own with `--libras-texts <file>`,
|
|
190
|
+
* repeatable (which implies `--libras`); a token the avatar carries no clip for is fingerspelled as written. It needs the
|
|
191
|
+
* glosser's environment, built once by `--libras-setup`; without it the delivery STOPS instead of shipping a player with nothing
|
|
192
|
+
* to sign but letters. Last, it writes `libras/offline-avatar.json`, the list of the avatar, clips, manifest, glosses and the
|
|
193
|
+
* build's three.js chunk with their sha256, by which a device with deaf mode on keeps the player for the days without a
|
|
194
|
+
* network — run after the build, which is what names the chunk.
|
|
195
|
+
* · `--libras-setup`: builds that environment (uv and Python 3.12), and does nothing else.
|
|
196
|
+
* · `--fonts <family,…|all|none>`, repeatable: the font LIBRARY's families the cartridges declare in `uses.fonts` (ADR-0255) —
|
|
197
|
+
* the engine packages only its own faces. Each face checked against the engine's catalogue (`platform/font-library.json`), each
|
|
198
|
+
* family with its licence and notice. Without the flag the delivery carries no library font, and a game that declares one is
|
|
199
|
+
* told so in `problems`. A family the library does not hold STOPS the command (exit 2).
|
|
200
|
+
*/
|
|
201
|
+
export function argumentosDaEntrega(args, ambiente = process.env) {
|
|
202
|
+
// ⚠️ `--base <value>` eats the token after it: without that, the value was read as the delivery folder (caught by its case).
|
|
203
|
+
let destino, base;
|
|
204
|
+
const reading = [];
|
|
205
|
+
const commands = [];
|
|
206
|
+
const fonts = [];
|
|
207
|
+
let libras = false;
|
|
208
|
+
const librasTexts = [];
|
|
209
|
+
for (let i = 0; i < args.length; i++) {
|
|
210
|
+
if (args[i] === '--libras') { libras = true; continue; }
|
|
211
|
+
if (args[i] === '--libras-texts') { const v = args[++i]; if (v) { librasTexts.push(v); libras = true; } continue; }
|
|
212
|
+
if (args[i] === '--base') { base = args[++i]; continue; }
|
|
213
|
+
// `--reading` alone — last, or before another flag — is every language; a value after it is a language, never the folder
|
|
214
|
+
if (args[i] === '--reading') {
|
|
215
|
+
const v = args[i + 1];
|
|
216
|
+
if (v === undefined || v.startsWith('--')) reading.push('all'); else { reading.push(v); i++; }
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (args[i] === '--commands') { const v = args[++i]; if (v) commands.push(v); continue; }
|
|
220
|
+
if (args[i] === '--fonts') { const v = args[++i]; if (v) fonts.push(v); continue; }
|
|
221
|
+
if (!args[i].startsWith('--') && destino === undefined) destino = args[i];
|
|
222
|
+
}
|
|
223
|
+
return { destino, kokoro: args.includes('--kokoro'), reading, commands, libras, librasTexts, librasSetup: args.includes('--libras-setup'),
|
|
224
|
+
fonts, base: base ?? ambiente.INCLUSIONIST_HEAVY_BASE ?? '' };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* THE SPOKEN LANGUAGES A DELIVERY CARRIES: those `--commands` named (less `none`, which names nothing), or — when the flag was
|
|
229
|
+
* not given — every language the catalogue has a command model for (ADR-0225 erratum). `languageOf` is the catalogue's
|
|
230
|
+
* `commandsLanguageOf`, so a fourth language with a model is carried by default the day it enters the catalogue. Named languages
|
|
231
|
+
* are base languages (`pt-BR` is `pt`).
|
|
232
|
+
* ⚠️ A NAMED LANGUAGE WITH NO MODEL THROWS, naming it, as `--reading` does: `--commands xx` used to carry the command runtime and
|
|
233
|
+
* no model at all, in silence.
|
|
234
|
+
*/
|
|
235
|
+
export function commandLanguagesOfTheDelivery(asked, catalogue, languageOf) {
|
|
236
|
+
const known = [...new Set(catalogue.map((p) => languageOf(p.id)).filter(Boolean))];
|
|
237
|
+
if (!asked.length) return known;
|
|
238
|
+
const base = (tag) => tag.split('-')[0].toLowerCase();
|
|
239
|
+
const named = asked.filter((lingua) => lingua !== 'none');
|
|
240
|
+
const unknown = named.filter((lingua) => !known.includes(base(lingua)));
|
|
241
|
+
if (unknown.length) {
|
|
242
|
+
throw new Error(`--commands ${unknown.join(', ')}: the catalogue has no command model for ${unknown.length > 1 ? 'these languages' : 'this language'} `
|
|
243
|
+
+ `— it has ${known.join(', ')}. Name one of them, \`--commands none\` for no command model, or leave the flag out for every language`);
|
|
244
|
+
}
|
|
245
|
+
return [...new Set(named.map(base))];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* THE READING LANGUAGES A DELIVERY CARRIES: none without `--reading` (a game that does not listen carries no model); every
|
|
250
|
+
* language the catalogue has a reading model for with `--reading` alone or `all` (ADR-0225 erratum); else those named, as base
|
|
251
|
+
* languages (`pt-BR` is `pt`), less `none`. `languageOf` is the catalogue's `readingLanguageOf`, so a fourth language with a model
|
|
252
|
+
* is carried by `all` the day it enters the catalogue.
|
|
253
|
+
* ⚠️ A NAMED LANGUAGE WITH NO MODEL THROWS, naming it: it used to carry nothing in silence — and a folder written after the flag
|
|
254
|
+
* (`--reading dist`) was read as a language and carried nothing just as quietly.
|
|
255
|
+
*/
|
|
256
|
+
export function readingLanguagesOfTheDelivery(asked, catalogue, languageOf) {
|
|
257
|
+
const known = [...new Set(catalogue.map((p) => languageOf(p.id)).filter(Boolean))];
|
|
258
|
+
const named = asked.filter((lingua) => lingua !== 'none' && lingua !== 'all');
|
|
259
|
+
const base = (tag) => tag.split('-')[0].toLowerCase();
|
|
260
|
+
const unknown = named.filter((lingua) => !known.includes(base(lingua)));
|
|
261
|
+
if (unknown.length) {
|
|
262
|
+
throw new Error(`--reading ${unknown.join(', ')}: the catalogue has no reading model for ${unknown.length > 1 ? 'these languages' : 'this language'} `
|
|
263
|
+
+ `— it has ${known.join(', ')}. Name one of them, or pass \`--reading\` alone for every language (the delivery folder goes `
|
|
264
|
+
+ 'before the flag: `inclusionist-heavy dist --reading`)');
|
|
265
|
+
}
|
|
266
|
+
if (asked.includes('all')) return known;
|
|
267
|
+
return [...new Set(named.map(base))];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* THE IDS A DELIVERY CARRIES, from the command's answers: the reading languages go in one list and the spoken ones in another,
|
|
272
|
+
* as the start asks for them. `readingLanguageOf` is needed only when `reading` names something.
|
|
273
|
+
*/
|
|
274
|
+
export function idsOfTheDelivery({ kokoro, reading, commands, libras }, { heavyAtBoot, catalogue, commandsLanguageOf, readingLanguageOf }) {
|
|
275
|
+
const spoken = commandLanguagesOfTheDelivery(commands, catalogue, commandsLanguageOf);
|
|
276
|
+
const read = reading.length ? readingLanguagesOfTheDelivery(reading, catalogue, readingLanguageOf) : [];
|
|
277
|
+
return [...new Set([
|
|
278
|
+
...heavyAtBoot({ kokoro }),
|
|
279
|
+
...(read.length ? heavyAtBoot({ kokoro: false, reading: read }) : []),
|
|
280
|
+
...heavyAtBoot({ kokoro: false, commands: spoken }),
|
|
281
|
+
...(libras ? heavyAtBoot({ kokoro: false, libras: true }) : []),
|
|
282
|
+
])];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** A `.env` beside the build, if there is one: Node reads it into `process.env`, and the command line still wins. */
|
|
286
|
+
export function carregarEnv(caminho = join(process.cwd(), '.env'), carregar = process.loadEnvFile) {
|
|
287
|
+
try { if (existsSync(caminho)) carregar.call(process, caminho); return true; } catch { return false; }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Run as a program (directly, or through the `inclusionist-heavy` shim, which may be a symlink): compare real paths.
|
|
291
|
+
const executado = (() => { try { return realpathSync(process.argv[1] ?? '') === realpathSync(fileURLToPath(import.meta.url)); } catch { return false; } })();
|
|
292
|
+
if (executado) {
|
|
293
|
+
carregarEnv();
|
|
294
|
+
const { destino, kokoro, reading, commands, libras, librasTexts, librasSetup, fonts, base } = argumentosDaEntrega(process.argv.slice(2));
|
|
295
|
+
if (librasSetup) {
|
|
296
|
+
try { console.log(`the Libras glosser's environment is ready: ${setUpGlosser()}`); process.exit(0); }
|
|
297
|
+
catch (e) { console.error(e instanceof Error ? e.message : String(e)); process.exit(1); }
|
|
298
|
+
}
|
|
299
|
+
if (!destino) {
|
|
300
|
+
console.error('usage: inclusionist-heavy <delivery folder, e.g. dist> [--kokoro] [--reading [all|pt|en|es|none]]… '
|
|
301
|
+
+ '[--commands pt|en|es|none]… [--fonts <family,…|all|none>]… [--libras] [--libras-texts <file>]… | --libras-setup');
|
|
302
|
+
if (reading.some((v) => v !== 'all')) console.error(`(the value after --reading is read as a language: «${reading.join(' ')}» — put the folder first)`);
|
|
303
|
+
process.exit(2);
|
|
304
|
+
}
|
|
305
|
+
const modulo = moduloDoPacote();
|
|
306
|
+
if (!existsSync(fileURLToPath(modulo))) { console.error('dist-pkg/platform/heavy.js is missing beside this script: in the engine repository, run `npm run build:pkg` first'); process.exit(2); }
|
|
307
|
+
const { HEAVY_FILES, deliveryPath, heavyAtBoot } = await import(modulo);
|
|
308
|
+
const { heavySourceOf } = await import(new URL('../dist-pkg/platform/heavy-mirror.js', import.meta.url).href);
|
|
309
|
+
const { LIBRAS_AVATAR_FOLDER, LIBRAS_AVATAR_STAGE_CHUNK, DELIVERY_LISTS, commandsLanguageOf, readingLanguageOf } = await import(new URL('../dist-pkg/platform/heavy-catalogue.js', import.meta.url).href);
|
|
310
|
+
// 📌 THE LANGUAGES FIRST, reading and command, before a byte is downloaded: a language the catalogue has no model for stops
|
|
311
|
+
// here, named
|
|
312
|
+
let read, spoken, typefaces;
|
|
313
|
+
// the ENGINE's font catalogue, from the package beside this script — the sha256 every delivered face must have (ADR-0255)
|
|
314
|
+
const library = JSON.parse(readFileSync(new URL('../dist-pkg/platform/font-library.json', import.meta.url), 'utf8'));
|
|
315
|
+
try {
|
|
316
|
+
read = readingLanguagesOfTheDelivery(reading, HEAVY_FILES, readingLanguageOf);
|
|
317
|
+
spoken = commandLanguagesOfTheDelivery(commands, HEAVY_FILES, commandsLanguageOf);
|
|
318
|
+
typefaces = fontFamiliesOfTheDelivery(fonts, library);
|
|
319
|
+
} catch (e) {
|
|
320
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
321
|
+
process.exit(2);
|
|
322
|
+
}
|
|
323
|
+
let librasGlosses = '';
|
|
324
|
+
let stageChunk = '';
|
|
325
|
+
if (libras) {
|
|
326
|
+
const { LIBRAS_GLOSSES_FILE } = await import(new URL('../dist-pkg/ui/libras-glosses.js', import.meta.url).href);
|
|
327
|
+
const { default: enginePt } = await import(new URL('../dist-pkg/i18n/pt.js', import.meta.url).href);
|
|
328
|
+
try {
|
|
329
|
+
// 📌 THE STAGE CHUNK AND THE GLOSSES FIRST, before a byte is downloaded: a build that never emitted the player, or a build
|
|
330
|
+
// machine with no glosser, learns it in a second, not after 32 MiB
|
|
331
|
+
stageChunk = stageChunkOf(destino, LIBRAS_AVATAR_STAGE_CHUNK);
|
|
332
|
+
const games = await Promise.all(librasTexts.map((file) => readTexts(file)));
|
|
333
|
+
const made = await deliverLibrasGlosses({
|
|
334
|
+
destino, folder: LIBRAS_AVATAR_FOLDER, glossesFile: LIBRAS_GLOSSES_FILE, dictionaries: [enginePt, ...games],
|
|
335
|
+
translate: (inputs) => runGlosser(inputs),
|
|
336
|
+
});
|
|
337
|
+
console.log(`glosses ${made.path} — ${made.texts} texts (the engine's${games.length ? ` and ${games.length} of the game's` : ''}), `
|
|
338
|
+
+ `${made.tokens} sign names`);
|
|
339
|
+
console.log(`signs ${made.signed.length} signed by the avatar's clips; ${made.fingerspelled.length} with no clip are fingerspelled `
|
|
340
|
+
+ '(scripts/libras-avatar.json)');
|
|
341
|
+
const { spelled } = made;
|
|
342
|
+
console.log(`spelled ${spelled.tokens} tokens: ${spelled.asWritten} as written on the screen (${spelled.ambiguous} of them `
|
|
343
|
+
+ `chosen by sentence order among several spellings, ${spelled.byStem} by the word's start), ${spelled.asTranslated} `
|
|
344
|
+
+ 'as the translator wrote them (no written word gives them)');
|
|
345
|
+
librasGlosses = made.path;
|
|
346
|
+
} catch (e) {
|
|
347
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
348
|
+
console.error('the Libras glosses were not made: a delivery built with --libras is not written without them');
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const ids = idsOfTheDelivery({ kokoro, reading, commands, libras },
|
|
353
|
+
{ heavyAtBoot, catalogue: HEAVY_FILES, commandsLanguageOf, readingLanguageOf });
|
|
354
|
+
console.log(`commands ${spoken.length ? spoken.join(', ') : 'none'}${commands.length ? '' : ' (every language, the default)'}`);
|
|
355
|
+
console.log(`reading ${read.length ? read.join(', ') : 'none'}${reading.includes('all') ? ' (every language)' : ''}`);
|
|
356
|
+
if (base) console.log(`base: ${base}`);
|
|
357
|
+
const { ok, linhas, licences } = await levarPesadosParaEntrega({
|
|
358
|
+
destino, pesados: HEAVY_FILES.filter((p) => ids.includes(p.id)), deliveryPath, base, fonteDe: heavySourceOf, catalogue: HEAVY_FILES,
|
|
359
|
+
});
|
|
360
|
+
for (const l of linhas) console.log(`${l.outcome.padEnd(9)} ${l.id}${(l.error ?? l.note) ? ` — ${l.error ?? l.note}` : ''}`);
|
|
361
|
+
for (const l of licences) console.log(`licence ${l.key} — ${l.folders.length} folder(s)`);
|
|
362
|
+
if (licences.length) console.log('notices heavy/THIRD-PARTY-NOTICES.md');
|
|
363
|
+
if (!ok) { console.error('a heavy file failed: the delivery is incomplete, and nothing unchecked was written'); process.exit(1); }
|
|
364
|
+
if (typefaces.length) {
|
|
365
|
+
const made = await levarFontesParaEntrega({ destino, families: typefaces, library, deliveryPath, base, fonteDe: heavySourceOf });
|
|
366
|
+
const written = made.linhas.filter((l) => l.outcome === 'escrito');
|
|
367
|
+
for (const l of made.linhas.filter((x) => x.outcome === 'falhou')) console.log(`falhou ${l.id} — ${l.error}`);
|
|
368
|
+
console.log(`fonts ${typefaces.length} families of the library — ${written.length} faces written, `
|
|
369
|
+
+ `${made.linhas.filter((l) => l.outcome === 'ja-tinha').length} already there, each checked by sha256`
|
|
370
|
+
+ `${made.ok ? ', each family with its licence and NOTICE.txt' : ''}`);
|
|
371
|
+
if (!made.ok) { console.error('a library font failed: its family is not delivered whole, and nothing unchecked was written'); process.exit(1); }
|
|
372
|
+
}
|
|
373
|
+
if (libras) {
|
|
374
|
+
try {
|
|
375
|
+
const pins = readAvatarPins();
|
|
376
|
+
const { files, bytes } = await deliverLibrasAvatar({ destino, folder: LIBRAS_AVATAR_FOLDER, pins, base });
|
|
377
|
+
console.log(`avatar ${LIBRAS_AVATAR_FOLDER} — ${files} files, ${(bytes / 1048576).toFixed(1)} MiB (ADR-0234)`);
|
|
378
|
+
// LAST, so it names what is really on the disk: the list a device keeps the player offline by (pillar 8)
|
|
379
|
+
const list = DELIVERY_LISTS.find((l) => l.id === 'libras:avatar:delivery');
|
|
380
|
+
const listed = writeAvatarList({ destino, list, folder: LIBRAS_AVATAR_FOLDER, pins, stageChunk, glosses: librasGlosses });
|
|
381
|
+
console.log(`offline ${listed.path} — ${listed.files} files (${stageChunk} among them), ${listed.bytes} bytes, each with its sha256`);
|
|
382
|
+
} catch (e) {
|
|
383
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
384
|
+
console.error('the Libras player was not delivered: this delivery cannot sign');
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|