@volter/editor-core 0.5.57
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/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The project-contract RESOLVER, host-neutral: how one module's relative
|
|
3
|
+
* imports are followed to the component contracts and prop-shape type aliases
|
|
4
|
+
* they bring into scope. Pure TypeScript AST work over a {@link ContractHost}
|
|
5
|
+
* that supplies the three things a file system used to — read a file, test
|
|
6
|
+
* for one, join a relative specifier — so the walk itself is independent of
|
|
7
|
+
* WHERE the sources are read from. The dev server supplies them with
|
|
8
|
+
* `node:fs` and a stamp-checked cache (`r3f-project-contracts.ts`); any other
|
|
9
|
+
* reader supplies its own, and gets the same contracts rather than a second
|
|
10
|
+
* answer ("HeroBox does not expose a scale prop" while the dev server wrote
|
|
11
|
+
* it — one editor, two answers — is what this split exists to prevent).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import ts from 'typescript';
|
|
15
|
+
import {
|
|
16
|
+
analyzeR3fComponentContracts,
|
|
17
|
+
builtinR3fContractsOfImport,
|
|
18
|
+
type ComponentPropSpec,
|
|
19
|
+
exportedR3fTypeAliases,
|
|
20
|
+
type R3fComponentContract,
|
|
21
|
+
type R3fTypeAlias,
|
|
22
|
+
} from './oid-transform';
|
|
23
|
+
import { localComponentPropSpecs } from './syntactic-prop-specs';
|
|
24
|
+
import { hasModifier, parseAuthoringTsx } from './ts-ast';
|
|
25
|
+
|
|
26
|
+
export interface ModuleAnalysis {
|
|
27
|
+
visible: Map<string, R3fComponentContract>;
|
|
28
|
+
exported: Map<string, R3fComponentContract>;
|
|
29
|
+
/** This module's own `export type X = …` declarations, for its importers. */
|
|
30
|
+
exportedTypeAliases: Map<string, R3fTypeAlias>;
|
|
31
|
+
/** Syntactic declared-prop specs per exported component
|
|
32
|
+
* (`syntactic-prop-specs.ts`) — the checker-free surface attached to OID
|
|
33
|
+
* entries so override detection and Apply-to-Component gate on facts
|
|
34
|
+
* instead of an absent `ts.Program`. */
|
|
35
|
+
exportedProps: Map<string, ComponentPropSpec[]>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const SOURCE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'] as const;
|
|
39
|
+
|
|
40
|
+
/** What a resolver needs from its host. Paths are whatever vocabulary the host
|
|
41
|
+
* speaks (absolute on the server, project-relative in storage); the resolver
|
|
42
|
+
* only passes them back. */
|
|
43
|
+
export interface ContractHost {
|
|
44
|
+
/** The file's text, or null when it cannot be read. */
|
|
45
|
+
read(file: string): string | null;
|
|
46
|
+
exists(file: string): boolean;
|
|
47
|
+
/** `dirname(fromFile)` joined with a relative specifier, normalized. */
|
|
48
|
+
resolve(fromFile: string, specifier: string): string;
|
|
49
|
+
extname(file: string): string;
|
|
50
|
+
/** `<base>/<name>` — the `index.*` candidate under a directory specifier. */
|
|
51
|
+
join(base: string, name: string): string;
|
|
52
|
+
/** Optional shared cache around one file's analysis (the server's
|
|
53
|
+
* stamp-checked map). Called with a thunk so the host decides whether to
|
|
54
|
+
* run it; a host without one analyzes every time within one resolver. */
|
|
55
|
+
analyzeFileCached?(file: string, analyze: () => ModuleAnalysis): ModuleAnalysis;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveRelativeModule(
|
|
59
|
+
host: ContractHost,
|
|
60
|
+
fromFile: string,
|
|
61
|
+
specifier: string,
|
|
62
|
+
): string | null {
|
|
63
|
+
if (!specifier.startsWith('.')) return null;
|
|
64
|
+
const base = host.resolve(fromFile, specifier);
|
|
65
|
+
const candidates = host.extname(base)
|
|
66
|
+
? [base]
|
|
67
|
+
: [
|
|
68
|
+
...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
69
|
+
...SOURCE_EXTENSIONS.map((extension) => host.join(base, `index${extension}`)),
|
|
70
|
+
];
|
|
71
|
+
return candidates.find((candidate) => host.exists(candidate)) ?? null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The project-local module a `import { … } from './x'` statement names, with
|
|
75
|
+
* its binding elements — or null when the statement is not one of those. */
|
|
76
|
+
function relativeNamedImport(
|
|
77
|
+
host: ContractHost,
|
|
78
|
+
statement: ts.Statement,
|
|
79
|
+
file: string,
|
|
80
|
+
): { target: string; elements: readonly ts.ImportSpecifier[] } | null {
|
|
81
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const target = resolveRelativeModule(host, file, statement.moduleSpecifier.text);
|
|
85
|
+
const bindings = statement.importClause?.namedBindings;
|
|
86
|
+
if (!target || !bindings || !ts.isNamedImports(bindings)) return null;
|
|
87
|
+
return { target, elements: bindings.elements };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class ProjectContractResolver {
|
|
91
|
+
private readonly cache = new Map<string, ModuleAnalysis>();
|
|
92
|
+
private readonly visiting = new Set<string>();
|
|
93
|
+
|
|
94
|
+
constructor(private readonly host: ContractHost) {}
|
|
95
|
+
|
|
96
|
+
importedForSource(code: string, file: string): Map<string, R3fComponentContract> {
|
|
97
|
+
return this.importedBindings(parseAuthoringTsx(file, code), file);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
typeAliasesForSource(code: string, file: string): Map<string, R3fTypeAlias> {
|
|
101
|
+
return this.importedTypeAliases(parseAuthoringTsx(file, code), file);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Declared-prop specs for every component a file's JSX can name — its own
|
|
106
|
+
* top-level components plus its relative imports (a local declaration
|
|
107
|
+
* shadows an import, the language's own rule). This is what the hosted
|
|
108
|
+
* stamping hook attaches to OID entries in place of the dev server's
|
|
109
|
+
* checker-resolved specs.
|
|
110
|
+
*/
|
|
111
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one bounded import-declaration pass, the same dispatch importedBindings carries.
|
|
112
|
+
propSpecsForSource(code: string, file: string): Map<string, ComponentPropSpec[]> {
|
|
113
|
+
const sf = parseAuthoringTsx(file, code);
|
|
114
|
+
const specs = new Map<string, ComponentPropSpec[]>();
|
|
115
|
+
for (const statement of sf.statements) {
|
|
116
|
+
if (
|
|
117
|
+
!ts.isImportDeclaration(statement) ||
|
|
118
|
+
!ts.isStringLiteral(statement.moduleSpecifier) ||
|
|
119
|
+
!statement.importClause
|
|
120
|
+
) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const target = resolveRelativeModule(this.host, file, statement.moduleSpecifier.text);
|
|
124
|
+
if (!target) continue;
|
|
125
|
+
const exported = this.analyzeFile(target).exportedProps;
|
|
126
|
+
const defaultName = statement.importClause.name?.text;
|
|
127
|
+
const defaultSpecs = exported.get('default');
|
|
128
|
+
if (defaultName && defaultSpecs) specs.set(defaultName, defaultSpecs);
|
|
129
|
+
const bindings = statement.importClause.namedBindings;
|
|
130
|
+
if (!bindings || !ts.isNamedImports(bindings)) continue;
|
|
131
|
+
for (const element of bindings.elements) {
|
|
132
|
+
const imported = exported.get(element.propertyName?.text ?? element.name.text);
|
|
133
|
+
if (imported) specs.set(element.name.text, imported);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const [name, local] of localComponentPropSpecs(sf, this.importedTypeAliases(sf, file))) {
|
|
137
|
+
specs.set(name, local);
|
|
138
|
+
}
|
|
139
|
+
return specs;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
analyzeSource(code: string, file: string): ModuleAnalysis {
|
|
143
|
+
const sf = parseAuthoringTsx(file, code);
|
|
144
|
+
const imported = this.importedBindings(sf, file);
|
|
145
|
+
// `analyzeR3fComponentContracts` re-parses `code`, so the aliases below
|
|
146
|
+
// must be resolved against the file each was WRITTEN in, not against this
|
|
147
|
+
// one — that pairing is what `R3fTypeAlias` carries.
|
|
148
|
+
const visible = analyzeR3fComponentContracts(
|
|
149
|
+
code,
|
|
150
|
+
file,
|
|
151
|
+
imported,
|
|
152
|
+
this.importedTypeAliases(sf, file),
|
|
153
|
+
);
|
|
154
|
+
const props = localComponentPropSpecs(sf, this.importedTypeAliases(sf, file));
|
|
155
|
+
return {
|
|
156
|
+
visible,
|
|
157
|
+
exported: this.exportsOf(sf, file, visible, (target) => this.analyzeFile(target).exported),
|
|
158
|
+
exportedTypeAliases: exportedR3fTypeAliases(sf),
|
|
159
|
+
exportedProps: this.exportsOf(
|
|
160
|
+
sf,
|
|
161
|
+
file,
|
|
162
|
+
props,
|
|
163
|
+
(target) => this.analyzeFile(target).exportedProps,
|
|
164
|
+
),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private analyzeFile(file: string): ModuleAnalysis {
|
|
169
|
+
const cached = this.cache.get(file);
|
|
170
|
+
if (cached) return cached;
|
|
171
|
+
if (this.visiting.has(file)) {
|
|
172
|
+
return {
|
|
173
|
+
visible: new Map(),
|
|
174
|
+
exported: new Map(),
|
|
175
|
+
exportedTypeAliases: new Map(),
|
|
176
|
+
exportedProps: new Map(),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
this.visiting.add(file);
|
|
180
|
+
try {
|
|
181
|
+
const analyze = (): ModuleAnalysis => {
|
|
182
|
+
const source = this.host.read(file);
|
|
183
|
+
return source === null
|
|
184
|
+
? {
|
|
185
|
+
visible: new Map(),
|
|
186
|
+
exported: new Map(),
|
|
187
|
+
exportedTypeAliases: new Map(),
|
|
188
|
+
exportedProps: new Map(),
|
|
189
|
+
}
|
|
190
|
+
: this.analyzeSource(source, file);
|
|
191
|
+
};
|
|
192
|
+
const analysis = this.host.analyzeFileCached
|
|
193
|
+
? this.host.analyzeFileCached(file, analyze)
|
|
194
|
+
: analyze();
|
|
195
|
+
this.cache.set(file, analysis);
|
|
196
|
+
return analysis;
|
|
197
|
+
} finally {
|
|
198
|
+
this.visiting.delete(file);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* The prop-shape type aliases one module imports, under their local names.
|
|
204
|
+
*
|
|
205
|
+
* The component-contract walk above already follows relative imports; this
|
|
206
|
+
* is the same walk for the OTHER thing a shared module exports. Without it,
|
|
207
|
+
* `typeAllowsStandardRootProps` stopped at the file boundary, so a project
|
|
208
|
+
* that declares its canonical prop shape once — the thing the authoring
|
|
209
|
+
* convention is asking for — read as forwarding nothing, and every prefab
|
|
210
|
+
* annotated with it drew a permanent R3F002 telling it to do what it was
|
|
211
|
+
* already doing.
|
|
212
|
+
*
|
|
213
|
+
* Only relative specifiers resolve. An installed package's `.d.ts` is not
|
|
214
|
+
* source this walk can trust, and the built-in prop-type table is how a
|
|
215
|
+
* package surface earns recognition instead.
|
|
216
|
+
*/
|
|
217
|
+
private importedTypeAliases(sf: ts.SourceFile, file: string): Map<string, R3fTypeAlias> {
|
|
218
|
+
const aliases = new Map<string, R3fTypeAlias>();
|
|
219
|
+
for (const statement of sf.statements) {
|
|
220
|
+
const named = relativeNamedImport(this.host, statement, file);
|
|
221
|
+
if (!named) continue;
|
|
222
|
+
const exported = this.analyzeFile(named.target).exportedTypeAliases;
|
|
223
|
+
for (const element of named.elements) {
|
|
224
|
+
const alias = exported.get(element.propertyName?.text ?? element.name.text);
|
|
225
|
+
if (alias) aliases.set(element.name.text, alias);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return aliases;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one bounded import-declaration pass keeps alias/default/named binding resolution together.
|
|
232
|
+
private importedBindings(sf: ts.SourceFile, file: string): Map<string, R3fComponentContract> {
|
|
233
|
+
const imported = new Map<string, R3fComponentContract>();
|
|
234
|
+
for (const statement of sf.statements) {
|
|
235
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
const target = resolveRelativeModule(this.host, file, statement.moduleSpecifier.text);
|
|
239
|
+
if (!target) {
|
|
240
|
+
// An installed package has no source here to walk. It contributes a
|
|
241
|
+
// contract only when the hand-audited built-in table names it; every
|
|
242
|
+
// other external binding stays conservative.
|
|
243
|
+
for (const [name, contract] of builtinR3fContractsOfImport(statement)) {
|
|
244
|
+
imported.set(name, contract);
|
|
245
|
+
}
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (!statement.importClause) continue;
|
|
249
|
+
const exported = this.analyzeFile(target).exported;
|
|
250
|
+
const defaultName = statement.importClause.name?.text;
|
|
251
|
+
const defaultContract = exported.get('default');
|
|
252
|
+
if (defaultName && defaultContract) imported.set(defaultName, defaultContract);
|
|
253
|
+
const bindings = statement.importClause.namedBindings;
|
|
254
|
+
if (!bindings || !ts.isNamedImports(bindings)) continue;
|
|
255
|
+
for (const element of bindings.elements) {
|
|
256
|
+
const contract = exported.get(element.propertyName?.text ?? element.name.text);
|
|
257
|
+
if (contract) imported.set(element.name.text, contract);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return imported;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: this is a bounded TypeScript export-syntax dispatcher, not application control flow.
|
|
264
|
+
private exportsOf<T>(
|
|
265
|
+
sf: ts.SourceFile,
|
|
266
|
+
file: string,
|
|
267
|
+
visible: ReadonlyMap<string, T>,
|
|
268
|
+
moduleExports: (target: string) => ReadonlyMap<string, T>,
|
|
269
|
+
): Map<string, T> {
|
|
270
|
+
const exported = new Map<string, T>();
|
|
271
|
+
for (const statement of sf.statements) {
|
|
272
|
+
if (
|
|
273
|
+
(ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) &&
|
|
274
|
+
statement.name &&
|
|
275
|
+
hasModifier(statement, ts.SyntaxKind.ExportKeyword)
|
|
276
|
+
) {
|
|
277
|
+
const contract = visible.get(statement.name.text);
|
|
278
|
+
if (contract) {
|
|
279
|
+
exported.set(
|
|
280
|
+
hasModifier(statement, ts.SyntaxKind.DefaultKeyword) ? 'default' : statement.name.text,
|
|
281
|
+
contract,
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (
|
|
286
|
+
ts.isVariableStatement(statement) &&
|
|
287
|
+
hasModifier(statement, ts.SyntaxKind.ExportKeyword)
|
|
288
|
+
) {
|
|
289
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
290
|
+
if (!ts.isIdentifier(declaration.name)) continue;
|
|
291
|
+
const contract = visible.get(declaration.name.text);
|
|
292
|
+
if (contract) exported.set(declaration.name.text, contract);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (ts.isExportAssignment(statement) && ts.isIdentifier(statement.expression)) {
|
|
296
|
+
const contract = visible.get(statement.expression.text);
|
|
297
|
+
if (contract) exported.set('default', contract);
|
|
298
|
+
}
|
|
299
|
+
if (!ts.isExportDeclaration(statement)) continue;
|
|
300
|
+
const target =
|
|
301
|
+
statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier)
|
|
302
|
+
? resolveRelativeModule(this.host, file, statement.moduleSpecifier.text)
|
|
303
|
+
: null;
|
|
304
|
+
// A BARREL (`export * from './Ramp'`) re-exports every name, and dropping
|
|
305
|
+
// it dropped the whole contract: racing-game reaches every one of its
|
|
306
|
+
// components through `src/models/index.ts`, so `<Ramp/>`, `<Train/>` and
|
|
307
|
+
// `<Vehicle/>` all read as "definition not in this file" and refused
|
|
308
|
+
// every transform write at their callsites. `export *` skips `default` by
|
|
309
|
+
// the language's own rule.
|
|
310
|
+
if (!statement.exportClause) {
|
|
311
|
+
if (!target) continue;
|
|
312
|
+
for (const [name, contract] of moduleExports(target)) {
|
|
313
|
+
if (name !== 'default') exported.set(name, contract);
|
|
314
|
+
}
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
const sourceContracts = target ? moduleExports(target) : visible;
|
|
318
|
+
if (!ts.isNamedExports(statement.exportClause)) continue;
|
|
319
|
+
for (const element of statement.exportClause.elements) {
|
|
320
|
+
const sourceName = element.propertyName?.text ?? element.name.text;
|
|
321
|
+
const contract = sourceContracts.get(sourceName);
|
|
322
|
+
if (contract) exported.set(element.name.text, contract);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return exported;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "warnings live on the row".
|
|
3
|
+
*
|
|
4
|
+
* The join that carries an R3F authorability diagnostic from where it is
|
|
5
|
+
* PRODUCED (a whole-file analysis, `r3fAuthoringDiagnostics`) to where it is
|
|
6
|
+
* READ (one hierarchy row). Pure, browser-safe, and unit-testable without a
|
|
7
|
+
* dev server: the two halves below are the entire mapping, and both the
|
|
8
|
+
* server-side annotator (`currentOidIndex`, `vite-plugin-ui-oid.ts`) and the
|
|
9
|
+
* client-side reader (`R3fSourceAuthoringAdapter.diagnosticsFor`) call one of
|
|
10
|
+
* them rather than re-deriving it.
|
|
11
|
+
*
|
|
12
|
+
* ## Why the join is by IDENTITY the index already holds, never by name
|
|
13
|
+
*
|
|
14
|
+
* Before H5 these diagnostics reached exactly one place: the dev server's
|
|
15
|
+
* terminal (and the `/__editor/state` warnings map), formatted to a string by
|
|
16
|
+
* `server/project-validation.ts`'s `validateSource`. A string in a log has no
|
|
17
|
+
* row identity at all, so the first question was what identity to give it.
|
|
18
|
+
*
|
|
19
|
+
* A diagnostic carries `{file, line, col, component}`. An `OidEntry` carries
|
|
20
|
+
* `{file, line, col, component, tag}` — where `component` is the component
|
|
21
|
+
* whose BODY lexically contains the element. Those two `component` fields mean
|
|
22
|
+
* the same thing on the definition side, and both positions come from
|
|
23
|
+
* `node.getStart()`, so the entry-side selection below needs no name
|
|
24
|
+
* resolution, no import walking, and no second derivation that could disagree
|
|
25
|
+
* with the first:
|
|
26
|
+
*
|
|
27
|
+
* - **at this element** — the diagnostic's `(file,line,col)` IS this entry's.
|
|
28
|
+
* That is R3F004 ("`<Enemy>` has no name"), whose subject is the callsite
|
|
29
|
+
* element itself. (R3F002/3/5 point at a function/variable NAME identifier
|
|
30
|
+
* or a `ref={…}` identifier, never at a `<`, so they can never collide with
|
|
31
|
+
* an element position and be misread as this kind.)
|
|
32
|
+
* - **inside this component** — the diagnostic names the component whose body
|
|
33
|
+
* contains this element (`d.component === entry.component`, same file). That
|
|
34
|
+
* is R3F002/R3F003/R3F005, which are ABOUT a definition.
|
|
35
|
+
*
|
|
36
|
+
* The second rule is what gets a definition-side warning onto an INSTANCE row
|
|
37
|
+
* in another file, and it needs no cross-file resolution: the oid transform
|
|
38
|
+
* stamps a component boundary with BOTH its callsite oid
|
|
39
|
+
* (`userData.authoringInstance`) and its definition-root oid (`userData.oid`),
|
|
40
|
+
* so the client already holds both index entries for one row — the same two
|
|
41
|
+
* entries H3's `sourceLocation`/`definitionLocation` return. {@link
|
|
42
|
+
* mergeRowDiagnostics} unions them.
|
|
43
|
+
*
|
|
44
|
+
* ## Why this cannot drift from index freshness
|
|
45
|
+
*
|
|
46
|
+
* It is not a separate channel. The diagnostics are attached to the entries of
|
|
47
|
+
* the very payload `refreshSourceState()` already fetches, computed in the same
|
|
48
|
+
* pass from the same file bytes. There is no second fetch to fall behind, no
|
|
49
|
+
* cache to invalidate, and no clock of its own: whatever makes the index stale
|
|
50
|
+
* makes them stale together, and whatever refreshes it refreshes them.
|
|
51
|
+
*
|
|
52
|
+
* ## A diagnostic that lands on no row does not vanish
|
|
53
|
+
*
|
|
54
|
+
* Some will not reach a row, and that is expected rather than a hole to be
|
|
55
|
+
* plugged: a component defined but never instantiated has no live object, a
|
|
56
|
+
* component whose definition file is not stamped as R3F is never analyzed here
|
|
57
|
+
* at all, and a hosted (no-dev-server) session has no analyzer (see
|
|
58
|
+
* `browser-oid-index.ts`). Nothing is LOST in any of those cases — this join is
|
|
59
|
+
* PURELY ADDITIVE. The channel these diagnostics have always had is untouched:
|
|
60
|
+
* `server/project-validation.ts`'s `validateSource` still formats every one of
|
|
61
|
+
* them into the dev server's terminal warning block and into the project
|
|
62
|
+
* warnings map that `/__editor/state` (and so `vgai status`) reports. Rows are
|
|
63
|
+
* a second, better-placed audience, not a replacement.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
import type { OidEntry, R3fAuthoringDiagnostic } from './oid-transform';
|
|
67
|
+
|
|
68
|
+
/** The per-entry selector {@link fileDiagnosticJoin} builds. */
|
|
69
|
+
export type EntryDiagnosticSelector = (
|
|
70
|
+
entry: Pick<OidEntry, 'line' | 'col' | 'component' | 'parentOid'>,
|
|
71
|
+
) => R3fAuthoringDiagnostic[] | undefined;
|
|
72
|
+
|
|
73
|
+
const position = (at: { line: number; col: number }): string => `${at.line}:${at.col}`;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Build the selector for ONE file: which of that file's diagnostics pertain to
|
|
77
|
+
* each of that file's oid entries. Both arguments must belong to the same
|
|
78
|
+
* file — the caller already has them grouped that way, so nothing here
|
|
79
|
+
* re-filters by file.
|
|
80
|
+
*
|
|
81
|
+
* The two rules of the module doc are applied as a PARTITION, not as an `||`,
|
|
82
|
+
* and that distinction is load-bearing. A diagnostic whose position is one of
|
|
83
|
+
* this file's stamped elements is ABOUT that element (R3F004); everything else
|
|
84
|
+
* is about a component definition (R3F002/3/5). Without the partition, an
|
|
85
|
+
* R3F004 on `<Enemy>` in a file that ALSO defines `Enemy` would match the
|
|
86
|
+
* component rule too and badge every element inside `Enemy`'s body — a warning
|
|
87
|
+
* about one callsite smeared across the definition's internals.
|
|
88
|
+
*
|
|
89
|
+
* Deriving the split from the data (does this position name a stamped
|
|
90
|
+
* element?) rather than from a hand-kept list of which codes are
|
|
91
|
+
* callsite-scoped is deliberate: a new R3F00x code classifies itself.
|
|
92
|
+
*
|
|
93
|
+
* The component rule additionally lands on that component's ROOT element only
|
|
94
|
+
* — the outermost stamped element of its body, recognized through `parentOid`
|
|
95
|
+
* (no parent, or a parent belonging to a different component). Two reasons,
|
|
96
|
+
* one practical and one exact: a definition's internals are not what an author
|
|
97
|
+
* is being warned about, and the root element is PRECISELY the entry an
|
|
98
|
+
* instance row reaches, because that oid is what the transform stamps on the
|
|
99
|
+
* boundary object as `userData.oid`. Anything looser would badge every
|
|
100
|
+
* `<mesh>` inside the component as well.
|
|
101
|
+
*
|
|
102
|
+
* The returned selector yields a fresh array, or `undefined` when nothing
|
|
103
|
+
* pertains — so the caller omits the field entirely instead of shipping an
|
|
104
|
+
* empty array on every entry.
|
|
105
|
+
*/
|
|
106
|
+
export function fileDiagnosticJoin(
|
|
107
|
+
fileEntries: ReadonlyMap<string, OidEntry>,
|
|
108
|
+
fileDiagnostics: readonly R3fAuthoringDiagnostic[],
|
|
109
|
+
): EntryDiagnosticSelector {
|
|
110
|
+
if (fileDiagnostics.length === 0) return () => undefined;
|
|
111
|
+
const elementPositions = new Set<string>();
|
|
112
|
+
for (const [, entry] of fileEntries) elementPositions.add(position(entry));
|
|
113
|
+
|
|
114
|
+
const atElement: R3fAuthoringDiagnostic[] = [];
|
|
115
|
+
const aboutComponent: R3fAuthoringDiagnostic[] = [];
|
|
116
|
+
for (const diagnostic of fileDiagnostics) {
|
|
117
|
+
(elementPositions.has(position(diagnostic)) ? atElement : aboutComponent).push(diagnostic);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const isComponentRoot = (entry: Pick<OidEntry, 'component' | 'parentOid'>): boolean => {
|
|
121
|
+
if (entry.parentOid === undefined) return true;
|
|
122
|
+
return fileEntries.get(entry.parentOid)?.component !== entry.component;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return (entry) => {
|
|
126
|
+
const pertinent = [
|
|
127
|
+
...atElement.filter((d) => d.line === entry.line && d.col === entry.col),
|
|
128
|
+
...(entry.component === null || !isComponentRoot(entry)
|
|
129
|
+
? []
|
|
130
|
+
: aboutComponent.filter((d) => d.component === entry.component)),
|
|
131
|
+
];
|
|
132
|
+
return pertinent.length > 0 ? pertinent : undefined;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Stable identity of one diagnostic, for the union below. Code + position is
|
|
137
|
+
* exact: two diagnostics of the same code at the same place ARE the same
|
|
138
|
+
* finding reached through two entries, which is the normal case when a
|
|
139
|
+
* component is defined and instantiated in one file. */
|
|
140
|
+
function diagnosticKey(diagnostic: R3fAuthoringDiagnostic): string {
|
|
141
|
+
return `${diagnostic.code}|${diagnostic.file}|${diagnostic.line}|${diagnostic.col}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Union of the diagnostics reachable from one ROW's index entries — its
|
|
146
|
+
* callsite entry and its definition-root entry — in that order, deduped.
|
|
147
|
+
* `undefined`/absent entries are skipped, so a row with only one of the two
|
|
148
|
+
* (a plain host element; an instance whose index entry has not landed) is the
|
|
149
|
+
* ordinary case, not a special one.
|
|
150
|
+
*/
|
|
151
|
+
export function mergeRowDiagnostics(
|
|
152
|
+
...entries: ReadonlyArray<Pick<OidEntry, 'diagnostics'> | undefined>
|
|
153
|
+
): R3fAuthoringDiagnostic[] {
|
|
154
|
+
const seen = new Set<string>();
|
|
155
|
+
const merged: R3fAuthoringDiagnostic[] = [];
|
|
156
|
+
for (const entry of entries) {
|
|
157
|
+
for (const diagnostic of entry?.diagnostics ?? []) {
|
|
158
|
+
const key = diagnosticKey(diagnostic);
|
|
159
|
+
if (seen.has(key)) continue;
|
|
160
|
+
seen.add(key);
|
|
161
|
+
merged.push(diagnostic);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return merged;
|
|
165
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/** Exact source tokens for native R3F scene attachments.
|
|
2
|
+
*
|
|
3
|
+
* These are not a VGAI environment format. `<color attach="background">`,
|
|
4
|
+
* `<fog attach="fog">`, and `<fogExp2 attach="fog">` are ordinary Fiber
|
|
5
|
+
* projections of THREE.Scene properties. The live Scene remains runtime truth;
|
|
6
|
+
* this metadata only identifies literal constructor arguments that can be
|
|
7
|
+
* changed without interpreting arbitrary project code.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import ts from 'typescript';
|
|
11
|
+
import { jsxAttribute, numericLiteral } from './ts-ast';
|
|
12
|
+
|
|
13
|
+
export interface R3fEnvironmentNumberBinding {
|
|
14
|
+
readonly value: number;
|
|
15
|
+
readonly start: number;
|
|
16
|
+
readonly end: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface R3fEnvironmentStringBinding {
|
|
20
|
+
readonly value: string;
|
|
21
|
+
readonly start: number;
|
|
22
|
+
readonly end: number;
|
|
23
|
+
readonly quote: "'" | '"' | '`';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type R3fEnvironmentBinding =
|
|
27
|
+
| {
|
|
28
|
+
readonly kind: 'background-color';
|
|
29
|
+
readonly color?: R3fEnvironmentStringBinding;
|
|
30
|
+
}
|
|
31
|
+
| {
|
|
32
|
+
readonly kind: 'fog';
|
|
33
|
+
readonly color?: R3fEnvironmentStringBinding;
|
|
34
|
+
readonly near?: R3fEnvironmentNumberBinding;
|
|
35
|
+
readonly far?: R3fEnvironmentNumberBinding;
|
|
36
|
+
}
|
|
37
|
+
| {
|
|
38
|
+
readonly kind: 'fog-exp2';
|
|
39
|
+
readonly color?: R3fEnvironmentStringBinding;
|
|
40
|
+
readonly density?: R3fEnvironmentNumberBinding;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function attributeString(attribute: ts.JsxAttribute | undefined): string | undefined {
|
|
44
|
+
const initializer = attribute?.initializer;
|
|
45
|
+
if (!initializer) return undefined;
|
|
46
|
+
if (ts.isStringLiteral(initializer)) return initializer.text;
|
|
47
|
+
const expression = ts.isJsxExpression(initializer) ? initializer.expression : undefined;
|
|
48
|
+
return expression &&
|
|
49
|
+
(ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression))
|
|
50
|
+
? expression.text
|
|
51
|
+
: undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function args(element: ts.JsxOpeningLikeElement): readonly ts.Expression[] | undefined {
|
|
55
|
+
const initializer = jsxAttribute(element, 'args')?.initializer;
|
|
56
|
+
const expression =
|
|
57
|
+
initializer && ts.isJsxExpression(initializer) ? initializer.expression : undefined;
|
|
58
|
+
return expression && ts.isArrayLiteralExpression(expression)
|
|
59
|
+
? expression.elements.filter(ts.isExpression)
|
|
60
|
+
: undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function numberBinding(
|
|
64
|
+
expression: ts.Expression | undefined,
|
|
65
|
+
sf: ts.SourceFile,
|
|
66
|
+
): R3fEnvironmentNumberBinding | undefined {
|
|
67
|
+
if (!expression) return undefined;
|
|
68
|
+
const value = numericLiteral(expression);
|
|
69
|
+
return value === undefined
|
|
70
|
+
? undefined
|
|
71
|
+
: { value, start: expression.getStart(sf), end: expression.getEnd() };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function stringBinding(
|
|
75
|
+
expression: ts.Expression | undefined,
|
|
76
|
+
sf: ts.SourceFile,
|
|
77
|
+
): R3fEnvironmentStringBinding | undefined {
|
|
78
|
+
if (
|
|
79
|
+
!expression ||
|
|
80
|
+
(!ts.isStringLiteral(expression) && !ts.isNoSubstitutionTemplateLiteral(expression))
|
|
81
|
+
) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const start = expression.getStart(sf);
|
|
85
|
+
const quote = sf.text[start];
|
|
86
|
+
if (quote !== "'" && quote !== '"' && quote !== '`') return undefined;
|
|
87
|
+
return { value: expression.text, start, end: expression.getEnd(), quote };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Bind recognized native scene attachments, including dynamic ones. Dynamic
|
|
91
|
+
* arguments deliberately produce a binding with missing tokens: the World
|
|
92
|
+
* Inspector can still identify the native mode but must keep that field
|
|
93
|
+
* read-only. */
|
|
94
|
+
export function environmentBindingsByElement(
|
|
95
|
+
sf: ts.SourceFile,
|
|
96
|
+
): Map<ts.JsxOpeningLikeElement, R3fEnvironmentBinding> {
|
|
97
|
+
const result = new Map<ts.JsxOpeningLikeElement, R3fEnvironmentBinding>();
|
|
98
|
+
const visit = (node: ts.Node): void => {
|
|
99
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
100
|
+
const tag = node.tagName.getText(sf);
|
|
101
|
+
const attachedTo = attributeString(jsxAttribute(node, 'attach'));
|
|
102
|
+
const values = args(node);
|
|
103
|
+
if (tag === 'color' && attachedTo === 'background') {
|
|
104
|
+
const color = stringBinding(values?.[0], sf);
|
|
105
|
+
result.set(node, {
|
|
106
|
+
kind: 'background-color',
|
|
107
|
+
...(color ? { color } : {}),
|
|
108
|
+
});
|
|
109
|
+
} else if (tag === 'fog' && attachedTo === 'fog') {
|
|
110
|
+
const color = stringBinding(values?.[0], sf);
|
|
111
|
+
const near = numberBinding(values?.[1], sf);
|
|
112
|
+
const far = numberBinding(values?.[2], sf);
|
|
113
|
+
result.set(node, {
|
|
114
|
+
kind: 'fog',
|
|
115
|
+
...(color ? { color } : {}),
|
|
116
|
+
...(near ? { near } : {}),
|
|
117
|
+
...(far ? { far } : {}),
|
|
118
|
+
});
|
|
119
|
+
} else if (tag === 'fogExp2' && attachedTo === 'fog') {
|
|
120
|
+
const color = stringBinding(values?.[0], sf);
|
|
121
|
+
const density = numberBinding(values?.[1], sf);
|
|
122
|
+
result.set(node, {
|
|
123
|
+
kind: 'fog-exp2',
|
|
124
|
+
...(color ? { color } : {}),
|
|
125
|
+
...(density ? { density } : {}),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
ts.forEachChild(node, visit);
|
|
130
|
+
};
|
|
131
|
+
visit(sf);
|
|
132
|
+
return result;
|
|
133
|
+
}
|