@abide/abide 0.28.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/CHANGELOG.md +607 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/bin/abide.ts +212 -0
- package/package.json +155 -0
- package/src/abideLsp.ts +211 -0
- package/src/abideModules.d.ts +8 -0
- package/src/abideResolverPlugin.ts +923 -0
- package/src/appEntry.ts +151 -0
- package/src/assets/app.html +12 -0
- package/src/build.ts +143 -0
- package/src/buildCli.ts +127 -0
- package/src/buildDisconnected.ts +118 -0
- package/src/bundleApp.ts +147 -0
- package/src/bundleDisconnectedEntry.ts +14 -0
- package/src/checkAbide.ts +77 -0
- package/src/cliEntry.ts +25 -0
- package/src/clientBuildPlugins.ts +33 -0
- package/src/clientEntry.ts +17 -0
- package/src/compile.ts +63 -0
- package/src/controlServerWorker.ts +426 -0
- package/src/devEntry.ts +250 -0
- package/src/discoveryEntry.ts +81 -0
- package/src/lib/bundle/BundleMenu.ts +12 -0
- package/src/lib/bundle/BundleMenuItem.ts +25 -0
- package/src/lib/bundle/BundleWindow.ts +37 -0
- package/src/lib/bundle/WEBVIEW_BUILD_REVISION.ts +9 -0
- package/src/lib/bundle/WEBVIEW_VERSION.ts +7 -0
- package/src/lib/bundle/bindConnectedFlag.ts +29 -0
- package/src/lib/bundle/bindRequestNavigate.ts +34 -0
- package/src/lib/bundle/buildWebviewLib.ts +111 -0
- package/src/lib/bundle/bundled.ts +35 -0
- package/src/lib/bundle/disconnected.abide +236 -0
- package/src/lib/bundle/disconnected.css +9 -0
- package/src/lib/bundle/ensureWebviewLib.ts +20 -0
- package/src/lib/bundle/exitWithParent.ts +28 -0
- package/src/lib/bundle/infoPlist.ts +46 -0
- package/src/lib/bundle/installDownloads.ts +24 -0
- package/src/lib/bundle/installMacMenu.ts +39 -0
- package/src/lib/bundle/listenLocalControlServer.ts +19 -0
- package/src/lib/bundle/native/abideMenu.mm +422 -0
- package/src/lib/bundle/native/webview.h +4557 -0
- package/src/lib/bundle/onMenu.ts +42 -0
- package/src/lib/bundle/openWebview.ts +104 -0
- package/src/lib/bundle/pngToIcns.ts +47 -0
- package/src/lib/bundle/probeAbideServer.ts +57 -0
- package/src/lib/bundle/resolveServerBinary.ts +12 -0
- package/src/lib/bundle/resolveWebviewLib.ts +53 -0
- package/src/lib/bundle/serverBinaryFilename.ts +8 -0
- package/src/lib/bundle/signMacApp.ts +37 -0
- package/src/lib/bundle/spawnEmbeddedServer.ts +64 -0
- package/src/lib/bundle/stableLocalPort.ts +19 -0
- package/src/lib/bundle/waitForServer.ts +23 -0
- package/src/lib/bundle/webviewCachePath.ts +23 -0
- package/src/lib/bundle/webviewLibName.ts +11 -0
- package/src/lib/cli/connectToServer.ts +23 -0
- package/src/lib/cli/createClient.ts +108 -0
- package/src/lib/cli/dispatchCommand.ts +71 -0
- package/src/lib/cli/loadEnvFromBinaryDir.ts +15 -0
- package/src/lib/cli/parseArgvForRpc.ts +100 -0
- package/src/lib/cli/printHelp.ts +119 -0
- package/src/lib/cli/printSessionHelp.ts +27 -0
- package/src/lib/cli/printSessionStatus.ts +21 -0
- package/src/lib/cli/printTrimmed.ts +8 -0
- package/src/lib/cli/printValue.ts +10 -0
- package/src/lib/cli/resolveCliTarget.ts +48 -0
- package/src/lib/cli/runCli.ts +176 -0
- package/src/lib/cli/runSession.ts +108 -0
- package/src/lib/cli/startLocalInstance.ts +14 -0
- package/src/lib/cli/tokenizeLine.ts +51 -0
- package/src/lib/cli/types/CliManifest.ts +9 -0
- package/src/lib/cli/types/CliManifestEntry.ts +17 -0
- package/src/lib/cli/types/CliTarget.ts +13 -0
- package/src/lib/mcp/annotationsForMethod.ts +29 -0
- package/src/lib/mcp/createMcpResourceServer.ts +102 -0
- package/src/lib/mcp/createMcpServer.ts +48 -0
- package/src/lib/mcp/dispatchMcpRequest.ts +138 -0
- package/src/lib/mcp/mcpResourceServerSlot.ts +18 -0
- package/src/lib/mcp/mcpSurface.ts +295 -0
- package/src/lib/mcp/toolResultFromResponse.ts +66 -0
- package/src/lib/mcp/types/JsonRpcRequest.ts +12 -0
- package/src/lib/mcp/types/JsonRpcResponse.ts +20 -0
- package/src/lib/mcp/types/McpResourceContents.ts +10 -0
- package/src/lib/mcp/types/McpResourceDescriptor.ts +6 -0
- package/src/lib/mcp/types/McpResourceServer.ts +12 -0
- package/src/lib/mcp/types/McpServer.ts +9 -0
- package/src/lib/mcp/types/McpServerOptions.ts +16 -0
- package/src/lib/server/AppModule.ts +47 -0
- package/src/lib/server/DELETE.ts +10 -0
- package/src/lib/server/GET.ts +10 -0
- package/src/lib/server/HEAD.ts +10 -0
- package/src/lib/server/PATCH.ts +10 -0
- package/src/lib/server/POST.ts +10 -0
- package/src/lib/server/PUT.ts +10 -0
- package/src/lib/server/agent.ts +86 -0
- package/src/lib/server/appDataDir.ts +16 -0
- package/src/lib/server/cli/buildEnvContent.ts +19 -0
- package/src/lib/server/cli/createTarGz.ts +77 -0
- package/src/lib/server/cli/handleCliDownload.ts +150 -0
- package/src/lib/server/cli/handleCliInstall.ts +37 -0
- package/src/lib/server/cli/installScript.ts +31 -0
- package/src/lib/server/cli/maxSourceMtime.ts +26 -0
- package/src/lib/server/cookies.ts +30 -0
- package/src/lib/server/env.ts +51 -0
- package/src/lib/server/error.ts +73 -0
- package/src/lib/server/json.ts +42 -0
- package/src/lib/server/jsonl.ts +47 -0
- package/src/lib/server/prompts/definePrompt.ts +21 -0
- package/src/lib/server/prompts/promptRegistry.ts +9 -0
- package/src/lib/server/prompts/registerPrompt.ts +6 -0
- package/src/lib/server/prompts/renderPromptTemplate.ts +17 -0
- package/src/lib/server/prompts/types/Prompt.ts +13 -0
- package/src/lib/server/prompts/types/PromptOptions.ts +12 -0
- package/src/lib/server/prompts/types/PromptRegistryEntry.ts +13 -0
- package/src/lib/server/prompts/types/PromptRoutes.ts +10 -0
- package/src/lib/server/reachable.ts +45 -0
- package/src/lib/server/redirect.ts +43 -0
- package/src/lib/server/request.ts +19 -0
- package/src/lib/server/rpc/defineVerb.ts +210 -0
- package/src/lib/server/rpc/dispatchVerbInProcess.ts +46 -0
- package/src/lib/server/rpc/findVerbByCommandName.ts +18 -0
- package/src/lib/server/rpc/parseArgs.ts +127 -0
- package/src/lib/server/rpc/readBodyWithinLimit.ts +44 -0
- package/src/lib/server/rpc/registerVerb.ts +6 -0
- package/src/lib/server/rpc/runWithVerbTimeout.ts +49 -0
- package/src/lib/server/rpc/types/RemoteHandler.ts +27 -0
- package/src/lib/server/rpc/types/RemoteRoutes.ts +13 -0
- package/src/lib/server/rpc/types/TypedResponse.ts +18 -0
- package/src/lib/server/rpc/types/VerbHelper.ts +87 -0
- package/src/lib/server/rpc/types/VerbRegistryEntry.ts +35 -0
- package/src/lib/server/rpc/unprocessed.ts +14 -0
- package/src/lib/server/rpc/verbRegistry.ts +11 -0
- package/src/lib/server/runtime/DEFAULT_PORT.ts +6 -0
- package/src/lib/server/runtime/DEV_READY_MESSAGE.ts +6 -0
- package/src/lib/server/runtime/DEV_REBUILD_MESSAGE.ts +4 -0
- package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +107 -0
- package/src/lib/server/runtime/SSR_SWAP_SCRIPT.ts +16 -0
- package/src/lib/server/runtime/acceptsGzip.ts +24 -0
- package/src/lib/server/runtime/buildCacheSnapshot.ts +61 -0
- package/src/lib/server/runtime/buildHealthPayload.ts +34 -0
- package/src/lib/server/runtime/buildInspectorSurface.ts +37 -0
- package/src/lib/server/runtime/buildOpenApiSpec.ts +106 -0
- package/src/lib/server/runtime/cacheControlForAsset.ts +22 -0
- package/src/lib/server/runtime/containsTraversal.ts +37 -0
- package/src/lib/server/runtime/createAppAssetServer.ts +76 -0
- package/src/lib/server/runtime/createAssetHeaderCache.ts +31 -0
- package/src/lib/server/runtime/createPublicAssetServer.ts +67 -0
- package/src/lib/server/runtime/createReachable.ts +109 -0
- package/src/lib/server/runtime/createRouteDispatcher.ts +127 -0
- package/src/lib/server/runtime/createServer.ts +674 -0
- package/src/lib/server/runtime/createUiPageRenderer.ts +181 -0
- package/src/lib/server/runtime/crossOriginForbidden.ts +17 -0
- package/src/lib/server/runtime/crossOriginGate.ts +29 -0
- package/src/lib/server/runtime/devClientFingerprint.ts +117 -0
- package/src/lib/server/runtime/devHotModuleResponse.ts +40 -0
- package/src/lib/server/runtime/devReloadResponse.ts +41 -0
- package/src/lib/server/runtime/disableIdleTimeoutForStream.ts +27 -0
- package/src/lib/server/runtime/envSchemaStore.ts +15 -0
- package/src/lib/server/runtime/findOpenPort.ts +21 -0
- package/src/lib/server/runtime/getActiveServer.ts +6 -0
- package/src/lib/server/runtime/globToPathSet.ts +29 -0
- package/src/lib/server/runtime/gzipResponse.ts +46 -0
- package/src/lib/server/runtime/inProcessServer.ts +20 -0
- package/src/lib/server/runtime/internalErrorResponse.ts +25 -0
- package/src/lib/server/runtime/isCrossOriginRequest.ts +23 -0
- package/src/lib/server/runtime/listenOnOpenPort.ts +36 -0
- package/src/lib/server/runtime/logExposedSurfaces.ts +156 -0
- package/src/lib/server/runtime/maybeMountInspector.ts +97 -0
- package/src/lib/server/runtime/mimeForExtension.ts +14 -0
- package/src/lib/server/runtime/pageUrlFromStore.ts +15 -0
- package/src/lib/server/runtime/parseIdleTimeout.ts +10 -0
- package/src/lib/server/runtime/parsePort.ts +11 -0
- package/src/lib/server/runtime/registryManifests.ts +66 -0
- package/src/lib/server/runtime/requestContext.ts +5 -0
- package/src/lib/server/runtime/resolvePageSnapshot.ts +25 -0
- package/src/lib/server/runtime/respondWithEmbeddedAsset.ts +18 -0
- package/src/lib/server/runtime/runWithRequestScope.ts +150 -0
- package/src/lib/server/runtime/safeJsonForScript.ts +17 -0
- package/src/lib/server/runtime/serializeCacheSnapshot.ts +45 -0
- package/src/lib/server/runtime/serverSlot.ts +13 -0
- package/src/lib/server/runtime/setActiveServer.ts +6 -0
- package/src/lib/server/runtime/snapshotEntryFromCache.ts +83 -0
- package/src/lib/server/runtime/streamCacheResolutions.ts +37 -0
- package/src/lib/server/runtime/streamFromIterator.ts +86 -0
- package/src/lib/server/runtime/types/Assets.ts +6 -0
- package/src/lib/server/runtime/types/DevReloadStamp.ts +18 -0
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +24 -0
- package/src/lib/server/runtime/types/InspectorCacheSnapshot.ts +11 -0
- package/src/lib/server/runtime/types/InspectorContext.ts +30 -0
- package/src/lib/server/runtime/types/InspectorSocket.ts +17 -0
- package/src/lib/server/runtime/types/InspectorSurface.ts +13 -0
- package/src/lib/server/runtime/types/InspectorVerb.ts +27 -0
- package/src/lib/server/runtime/types/RequestStore.ts +55 -0
- package/src/lib/server/runtime/warnUnguardedMcp.ts +32 -0
- package/src/lib/server/runtime/withResponseDefaults.ts +24 -0
- package/src/lib/server/server.ts +33 -0
- package/src/lib/server/socket.ts +32 -0
- package/src/lib/server/sockets/createSocketDispatcher.ts +337 -0
- package/src/lib/server/sockets/defineSocket.ts +179 -0
- package/src/lib/server/sockets/lookupSocket.ts +6 -0
- package/src/lib/server/sockets/registerSocket.ts +6 -0
- package/src/lib/server/sockets/socketOperations.ts +36 -0
- package/src/lib/server/sockets/socketRegistry.ts +9 -0
- package/src/lib/server/sockets/types/Socket.ts +23 -0
- package/src/lib/server/sockets/types/SocketClientFrame.ts +19 -0
- package/src/lib/server/sockets/types/SocketOperation.ts +22 -0
- package/src/lib/server/sockets/types/SocketOptions.ts +26 -0
- package/src/lib/server/sockets/types/SocketRegistryEntry.ts +19 -0
- package/src/lib/server/sockets/types/SocketRoutes.ts +10 -0
- package/src/lib/server/sockets/types/SocketServerFrame.ts +24 -0
- package/src/lib/server/sse.ts +54 -0
- package/src/lib/shared/ABIDE_PACKAGE_NAME.ts +7 -0
- package/src/lib/shared/ABIDE_VERSION.ts +9 -0
- package/src/lib/shared/CACHE_CONTROL_VALUES.ts +16 -0
- package/src/lib/shared/CACHE_WRAPPED.ts +8 -0
- package/src/lib/shared/CLI_PATH.ts +7 -0
- package/src/lib/shared/DEV_HOT_PREFIX.ts +7 -0
- package/src/lib/shared/DEV_RELOAD_PATH.ts +6 -0
- package/src/lib/shared/HEALTH_PATH.ts +7 -0
- package/src/lib/shared/HttpError.ts +20 -0
- package/src/lib/shared/IDENTITY_PATH.ts +6 -0
- package/src/lib/shared/INSPECTOR_PATH.ts +7 -0
- package/src/lib/shared/NAV_HEADER.ts +8 -0
- package/src/lib/shared/OFFLINE_HEADER.ts +8 -0
- package/src/lib/shared/REMOTE_FUNCTION.ts +8 -0
- package/src/lib/shared/REPLAYABLE_METHODS.ts +12 -0
- package/src/lib/shared/SOCKETS_PATH.ts +7 -0
- package/src/lib/shared/STREAMING_CONTENT_TYPES.ts +11 -0
- package/src/lib/shared/SocketDisconnectedError.ts +13 -0
- package/src/lib/shared/TEXT_PLAIN.ts +7 -0
- package/src/lib/shared/abideImportName.ts +44 -0
- package/src/lib/shared/abideLog.ts +38 -0
- package/src/lib/shared/activeCacheStore.ts +20 -0
- package/src/lib/shared/activePage.ts +25 -0
- package/src/lib/shared/appDataDir.ts +34 -0
- package/src/lib/shared/appNameSlot.ts +10 -0
- package/src/lib/shared/basePath.ts +10 -0
- package/src/lib/shared/basePathFromAppUrl.ts +20 -0
- package/src/lib/shared/baseSlot.ts +14 -0
- package/src/lib/shared/binaryDirEnvPath.ts +12 -0
- package/src/lib/shared/browserClientFlags.ts +10 -0
- package/src/lib/shared/buildRpcProxy.ts +39 -0
- package/src/lib/shared/buildRpcRequest.ts +70 -0
- package/src/lib/shared/buildSocketOverChannel.ts +58 -0
- package/src/lib/shared/bundleLayout.ts +36 -0
- package/src/lib/shared/cache.ts +951 -0
- package/src/lib/shared/cacheEntryFromSnapshot.ts +59 -0
- package/src/lib/shared/cacheStoreSlot.ts +16 -0
- package/src/lib/shared/cacheStores.ts +10 -0
- package/src/lib/shared/canonicalJson.ts +63 -0
- package/src/lib/shared/carriesBodyArgs.ts +13 -0
- package/src/lib/shared/clearLastConnection.ts +7 -0
- package/src/lib/shared/commandNameForUrl.ts +17 -0
- package/src/lib/shared/createCacheStore.ts +104 -0
- package/src/lib/shared/createChannelLog.ts +122 -0
- package/src/lib/shared/createLifecycleChannel.ts +56 -0
- package/src/lib/shared/createLivenessWatch.ts +118 -0
- package/src/lib/shared/createPushIterator.ts +127 -0
- package/src/lib/shared/createRemoteFunction.ts +122 -0
- package/src/lib/shared/createSubscriber.ts +55 -0
- package/src/lib/shared/createTraceContext.ts +21 -0
- package/src/lib/shared/dataDirEnvPath.ts +12 -0
- package/src/lib/shared/decodeResponse.ts +47 -0
- package/src/lib/shared/detectTarget.ts +27 -0
- package/src/lib/shared/detectVerbMethod.ts +17 -0
- package/src/lib/shared/emitLogRecord.ts +190 -0
- package/src/lib/shared/exeSuffix.ts +9 -0
- package/src/lib/shared/exitOnBuildFailure.ts +17 -0
- package/src/lib/shared/extraForwardHeaders.ts +16 -0
- package/src/lib/shared/fileStem.ts +9 -0
- package/src/lib/shared/findExportCallSite.ts +476 -0
- package/src/lib/shared/formatTraceparent.ts +6 -0
- package/src/lib/shared/forwardHeaders.ts +44 -0
- package/src/lib/shared/getRemoteMeta.ts +5 -0
- package/src/lib/shared/globalCacheStore.ts +15 -0
- package/src/lib/shared/globalCacheStoreSlot.ts +14 -0
- package/src/lib/shared/health.ts +179 -0
- package/src/lib/shared/healthReadSlot.ts +11 -0
- package/src/lib/shared/healthSeedSlot.ts +12 -0
- package/src/lib/shared/html.ts +38 -0
- package/src/lib/shared/importNamesToStrip.ts +13 -0
- package/src/lib/shared/invalidateEvent.ts +11 -0
- package/src/lib/shared/invalidateTripwire.ts +40 -0
- package/src/lib/shared/isAbideHealthPayload.ts +11 -0
- package/src/lib/shared/isCompileTarget.ts +15 -0
- package/src/lib/shared/isDebugEnabled.ts +26 -0
- package/src/lib/shared/isDebugNegated.ts +19 -0
- package/src/lib/shared/isModuleNotFound.ts +16 -0
- package/src/lib/shared/isReadOnlyMethod.ts +14 -0
- package/src/lib/shared/isReplayableMethod.ts +7 -0
- package/src/lib/shared/isStreamingResponse.ts +11 -0
- package/src/lib/shared/isSubscribable.ts +15 -0
- package/src/lib/shared/jsonSchemaForPromptArguments.ts +29 -0
- package/src/lib/shared/jsonSchemaForSchema.ts +39 -0
- package/src/lib/shared/jsonlErrorFrame.ts +24 -0
- package/src/lib/shared/keyForRemoteCall.ts +29 -0
- package/src/lib/shared/keyMatchesPrefix.ts +9 -0
- package/src/lib/shared/lastConnectionPath.ts +7 -0
- package/src/lib/shared/layoutChainForRoute.ts +22 -0
- package/src/lib/shared/loadEnvFile.ts +17 -0
- package/src/lib/shared/loadEnvFromDataDir.ts +14 -0
- package/src/lib/shared/log.ts +24 -0
- package/src/lib/shared/logClosingRecord.ts +28 -0
- package/src/lib/shared/logTapSlot.ts +13 -0
- package/src/lib/shared/manifestModule.ts +39 -0
- package/src/lib/shared/matchesDebugPattern.ts +16 -0
- package/src/lib/shared/memoizeByKey.ts +32 -0
- package/src/lib/shared/normalizeTarget.ts +10 -0
- package/src/lib/shared/online.ts +51 -0
- package/src/lib/shared/page.ts +30 -0
- package/src/lib/shared/pageSlot.ts +17 -0
- package/src/lib/shared/pageUrlForFile.ts +14 -0
- package/src/lib/shared/parseBoundedEnvInt.ts +20 -0
- package/src/lib/shared/parseDebugPatterns.ts +21 -0
- package/src/lib/shared/parseEnv.ts +30 -0
- package/src/lib/shared/parsePromptMarkdown.ts +35 -0
- package/src/lib/shared/parseRouteSegments.ts +22 -0
- package/src/lib/shared/parseTraceparent.ts +26 -0
- package/src/lib/shared/pending.ts +30 -0
- package/src/lib/shared/prepareRpcModule.ts +59 -0
- package/src/lib/shared/prepareSocketModule.ts +49 -0
- package/src/lib/shared/probeRegistries.ts +68 -0
- package/src/lib/shared/producerKey.ts +32 -0
- package/src/lib/shared/programNameForPackage.ts +14 -0
- package/src/lib/shared/promptNameForFile.ts +10 -0
- package/src/lib/shared/queryStringFromArgs.ts +27 -0
- package/src/lib/shared/randomHexId.ts +14 -0
- package/src/lib/shared/readEnvFile.ts +15 -0
- package/src/lib/shared/readLastConnection.ts +18 -0
- package/src/lib/shared/readPackageJson.ts +9 -0
- package/src/lib/shared/recordRemoteMeta.ts +5 -0
- package/src/lib/shared/refreshing.ts +31 -0
- package/src/lib/shared/remoteMetaStore.ts +16 -0
- package/src/lib/shared/requestScopeSlot.ts +15 -0
- package/src/lib/shared/resolveClientFlags.ts +20 -0
- package/src/lib/shared/responseErrorText.ts +9 -0
- package/src/lib/shared/rpcTimeoutSlot.ts +9 -0
- package/src/lib/shared/rpcUrlForFile.ts +19 -0
- package/src/lib/shared/runningAsStandaloneBinary.ts +13 -0
- package/src/lib/shared/selectorMatcher.ts +68 -0
- package/src/lib/shared/selectorPrefix.ts +39 -0
- package/src/lib/shared/serializeEnv.ts +18 -0
- package/src/lib/shared/setAppName.ts +5 -0
- package/src/lib/shared/setBaseResolver.ts +6 -0
- package/src/lib/shared/setCacheStoreResolver.ts +6 -0
- package/src/lib/shared/setGlobalCacheStoreResolver.ts +6 -0
- package/src/lib/shared/setPageResolver.ts +7 -0
- package/src/lib/shared/setRequestScopeResolver.ts +6 -0
- package/src/lib/shared/snippet.ts +25 -0
- package/src/lib/shared/socketNameForFile.ts +11 -0
- package/src/lib/shared/socketTapSlot.ts +12 -0
- package/src/lib/shared/sseErrorFrame.ts +29 -0
- package/src/lib/shared/streamResponse.ts +169 -0
- package/src/lib/shared/stripImport.ts +27 -0
- package/src/lib/shared/subscribableFromResponse.ts +51 -0
- package/src/lib/shared/tailProbeSlot.ts +16 -0
- package/src/lib/shared/toBunRoutePattern.ts +28 -0
- package/src/lib/shared/toScopeSet.ts +4 -0
- package/src/lib/shared/trace.ts +16 -0
- package/src/lib/shared/types/CacheEntry.ts +84 -0
- package/src/lib/shared/types/CacheInvalidation.ts +9 -0
- package/src/lib/shared/types/CacheOnContext.ts +25 -0
- package/src/lib/shared/types/CacheOptions.ts +39 -0
- package/src/lib/shared/types/CacheSelector.ts +17 -0
- package/src/lib/shared/types/CacheSnapshot.ts +16 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +17 -0
- package/src/lib/shared/types/CacheStats.ts +13 -0
- package/src/lib/shared/types/CacheStore.ts +39 -0
- package/src/lib/shared/types/ChannelLog.ts +13 -0
- package/src/lib/shared/types/ClientFlags.ts +11 -0
- package/src/lib/shared/types/CompileTarget.ts +6 -0
- package/src/lib/shared/types/FrameworkLog.ts +13 -0
- package/src/lib/shared/types/HttpVerb.ts +1 -0
- package/src/lib/shared/types/LastConnection.ts +9 -0
- package/src/lib/shared/types/Log.ts +13 -0
- package/src/lib/shared/types/LogRecord.ts +42 -0
- package/src/lib/shared/types/LogVoice.ts +7 -0
- package/src/lib/shared/types/PageSnapshot.ts +14 -0
- package/src/lib/shared/types/PromptArgument.ts +12 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +14 -0
- package/src/lib/shared/types/RemoteCallable.ts +12 -0
- package/src/lib/shared/types/RemoteFunction.ts +47 -0
- package/src/lib/shared/types/ReplayableMethod.ts +7 -0
- package/src/lib/shared/types/RequestScopeInfo.ts +16 -0
- package/src/lib/shared/types/RpcInvoker.ts +6 -0
- package/src/lib/shared/types/SocketChannel.ts +17 -0
- package/src/lib/shared/types/SocketSubCallbacks.ts +13 -0
- package/src/lib/shared/types/StandardSchemaV1.ts +56 -0
- package/src/lib/shared/types/StreamedResolution.ts +10 -0
- package/src/lib/shared/types/Subscribable.ts +26 -0
- package/src/lib/shared/types/TailHooks.ts +12 -0
- package/src/lib/shared/types/TailOptions.ts +10 -0
- package/src/lib/shared/types/TraceContext.ts +17 -0
- package/src/lib/shared/url.ts +118 -0
- package/src/lib/shared/withBase.ts +11 -0
- package/src/lib/shared/withBaseUrl.ts +17 -0
- package/src/lib/shared/withJsonSchema.ts +21 -0
- package/src/lib/shared/writeDts.ts +12 -0
- package/src/lib/shared/writeHealthDts.ts +36 -0
- package/src/lib/shared/writeLastConnection.ts +13 -0
- package/src/lib/shared/writePublicAssetsDts.ts +31 -0
- package/src/lib/shared/writeRoutesDts.ts +73 -0
- package/src/lib/shared/writeRpcDts.ts +49 -0
- package/src/lib/shared/writeTestRpcDts.ts +45 -0
- package/src/lib/shared/writeTestSocketsDts.ts +34 -0
- package/src/lib/test/assertAgentFrameConformance.ts +73 -0
- package/src/lib/test/createScriptedSurface.ts +45 -0
- package/src/lib/test/createTestApp.ts +203 -0
- package/src/lib/test/createTestSocketChannel.ts +142 -0
- package/src/lib/ui/README.md +86 -0
- package/src/lib/ui/compile/SSR_ESCAPE.ts +25 -0
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +36 -0
- package/src/lib/ui/compile/VOID_TAGS.ts +21 -0
- package/src/lib/ui/compile/abideUiPlugin.ts +65 -0
- package/src/lib/ui/compile/analyzeComponent.ts +117 -0
- package/src/lib/ui/compile/assetModulesFile.ts +32 -0
- package/src/lib/ui/compile/branchElements.ts +50 -0
- package/src/lib/ui/compile/collectAbideDiagnostics.ts +59 -0
- package/src/lib/ui/compile/compileComponent.ts +20 -0
- package/src/lib/ui/compile/compileModule.ts +116 -0
- package/src/lib/ui/compile/compileSSR.ts +36 -0
- package/src/lib/ui/compile/compileShadow.ts +352 -0
- package/src/lib/ui/compile/createShadowLanguageService.ts +197 -0
- package/src/lib/ui/compile/createShadowProgram.ts +96 -0
- package/src/lib/ui/compile/decodeHtmlEntities.ts +49 -0
- package/src/lib/ui/compile/desugarSignals.ts +133 -0
- package/src/lib/ui/compile/escapeHtml.ts +15 -0
- package/src/lib/ui/compile/generateBuild.ts +638 -0
- package/src/lib/ui/compile/generateSSR.ts +380 -0
- package/src/lib/ui/compile/groupBindParts.ts +28 -0
- package/src/lib/ui/compile/hoistCells.ts +120 -0
- package/src/lib/ui/compile/loadShadowTsConfig.ts +31 -0
- package/src/lib/ui/compile/lowerDocAccess.ts +202 -0
- package/src/lib/ui/compile/nearestProjectRoot.ts +16 -0
- package/src/lib/ui/compile/parseTemplate.ts +396 -0
- package/src/lib/ui/compile/partitionSlots.ts +36 -0
- package/src/lib/ui/compile/prepareNestedScript.ts +42 -0
- package/src/lib/ui/compile/remapShadowDiagnostic.ts +30 -0
- package/src/lib/ui/compile/renameSignalRefs.ts +85 -0
- package/src/lib/ui/compile/resolveAbideImports.ts +29 -0
- package/src/lib/ui/compile/scopeCss.ts +115 -0
- package/src/lib/ui/compile/shadowNaming.ts +11 -0
- package/src/lib/ui/compile/sourceToShadowOffset.ts +24 -0
- package/src/lib/ui/compile/staticAttrValue.ts +13 -0
- package/src/lib/ui/compile/stripEffects.ts +32 -0
- package/src/lib/ui/compile/types/AbideDiagnostic.ts +14 -0
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +25 -0
- package/src/lib/ui/compile/types/CompiledShadow.ts +15 -0
- package/src/lib/ui/compile/types/TemplateAttr.ts +16 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +78 -0
- package/src/lib/ui/compile/types/TextPart.ts +8 -0
- package/src/lib/ui/derived.ts +28 -0
- package/src/lib/ui/doc.ts +15 -0
- package/src/lib/ui/dom/appendSnippet.ts +34 -0
- package/src/lib/ui/dom/appendStatic.ts +27 -0
- package/src/lib/ui/dom/appendText.ts +114 -0
- package/src/lib/ui/dom/applyResolved.ts +72 -0
- package/src/lib/ui/dom/attach.ts +20 -0
- package/src/lib/ui/dom/attr.ts +19 -0
- package/src/lib/ui/dom/awaitBlock.ts +224 -0
- package/src/lib/ui/dom/cloneStatic.ts +52 -0
- package/src/lib/ui/dom/each.ts +115 -0
- package/src/lib/ui/dom/eachAsync.ts +153 -0
- package/src/lib/ui/dom/hydrate.ts +35 -0
- package/src/lib/ui/dom/mount.ts +29 -0
- package/src/lib/ui/dom/mountChild.ts +33 -0
- package/src/lib/ui/dom/on.ts +15 -0
- package/src/lib/ui/dom/openChild.ts +22 -0
- package/src/lib/ui/dom/openRoot.ts +20 -0
- package/src/lib/ui/dom/switchBlock.ts +75 -0
- package/src/lib/ui/dom/text.ts +20 -0
- package/src/lib/ui/dom/tryBlock.ts +112 -0
- package/src/lib/ui/dom/types/EachRow.ts +3 -0
- package/src/lib/ui/dom/types/SwitchCase.ts +6 -0
- package/src/lib/ui/dom/when.ts +73 -0
- package/src/lib/ui/effect.ts +16 -0
- package/src/lib/ui/installHotBridge.ts +73 -0
- package/src/lib/ui/matchRoute.ts +89 -0
- package/src/lib/ui/navigate.ts +17 -0
- package/src/lib/ui/probeNavigation.ts +33 -0
- package/src/lib/ui/remoteProxy.ts +97 -0
- package/src/lib/ui/renderChain.ts +50 -0
- package/src/lib/ui/renderToStream.ts +104 -0
- package/src/lib/ui/router.ts +286 -0
- package/src/lib/ui/runtime/OUTLET_TAG.ts +8 -0
- package/src/lib/ui/runtime/OWNER.ts +8 -0
- package/src/lib/ui/runtime/REACTIVE_CONTEXT.ts +14 -0
- package/src/lib/ui/runtime/RENDER.ts +23 -0
- package/src/lib/ui/runtime/RESUME.ts +16 -0
- package/src/lib/ui/runtime/applyPatchToTree.ts +41 -0
- package/src/lib/ui/runtime/claimChild.ts +10 -0
- package/src/lib/ui/runtime/clientPage.ts +16 -0
- package/src/lib/ui/runtime/createComputedNode.ts +16 -0
- package/src/lib/ui/runtime/createDoc.ts +177 -0
- package/src/lib/ui/runtime/createEffectNode.ts +58 -0
- package/src/lib/ui/runtime/createSignalNode.ts +16 -0
- package/src/lib/ui/runtime/detachLink.ts +21 -0
- package/src/lib/ui/runtime/endTracking.ts +24 -0
- package/src/lib/ui/runtime/enterRenderPass.ts +12 -0
- package/src/lib/ui/runtime/exitRenderPass.ts +7 -0
- package/src/lib/ui/runtime/firstOutlet.ts +22 -0
- package/src/lib/ui/runtime/flushEffects.ts +17 -0
- package/src/lib/ui/runtime/hotInstances.ts +10 -0
- package/src/lib/ui/runtime/hotReloadEnabled.ts +8 -0
- package/src/lib/ui/runtime/hotReplace.ts +25 -0
- package/src/lib/ui/runtime/nextBlockId.ts +11 -0
- package/src/lib/ui/runtime/pathExists.ts +23 -0
- package/src/lib/ui/runtime/readNode.ts +17 -0
- package/src/lib/ui/runtime/registerHotInstance.ts +23 -0
- package/src/lib/ui/runtime/runNode.ts +28 -0
- package/src/lib/ui/runtime/runtimePath.ts +9 -0
- package/src/lib/ui/runtime/scope.ts +24 -0
- package/src/lib/ui/runtime/toTeardown.ts +26 -0
- package/src/lib/ui/runtime/track.ts +58 -0
- package/src/lib/ui/runtime/trigger.ts +44 -0
- package/src/lib/ui/runtime/types/Cell.ts +5 -0
- package/src/lib/ui/runtime/types/Derived.ts +3 -0
- package/src/lib/ui/runtime/types/Doc.ts +19 -0
- package/src/lib/ui/runtime/types/EffectResult.ts +10 -0
- package/src/lib/ui/runtime/types/HotInstance.ts +14 -0
- package/src/lib/ui/runtime/types/NavVerdict.ts +9 -0
- package/src/lib/ui/runtime/types/Patch.ts +11 -0
- package/src/lib/ui/runtime/types/ReactiveLink.ts +21 -0
- package/src/lib/ui/runtime/types/ReactiveNode.ts +25 -0
- package/src/lib/ui/runtime/types/Route.ts +8 -0
- package/src/lib/ui/runtime/types/RouteLoader.ts +7 -0
- package/src/lib/ui/runtime/types/SsrRender.ts +22 -0
- package/src/lib/ui/runtime/types/State.ts +3 -0
- package/src/lib/ui/runtime/types/Teardown.ts +5 -0
- package/src/lib/ui/runtime/types/UiComponent.ts +16 -0
- package/src/lib/ui/runtime/types/UiProps.ts +15 -0
- package/src/lib/ui/runtime/unlinkDeps.ts +20 -0
- package/src/lib/ui/runtime/untrack.ts +20 -0
- package/src/lib/ui/runtime/valueAtPath.ts +18 -0
- package/src/lib/ui/runtime/writeNode.ts +16 -0
- package/src/lib/ui/socketChannel.ts +227 -0
- package/src/lib/ui/socketProxy.ts +25 -0
- package/src/lib/ui/startClient.ts +58 -0
- package/src/lib/ui/state.ts +25 -0
- package/src/lib/ui/tail.ts +324 -0
- package/src/lib/ui/types/Layouts.ts +9 -0
- package/src/lib/ui/types/Pages.ts +8 -0
- package/src/preload.ts +19 -0
- package/src/scaffold.ts +153 -0
- package/src/serverBuildPlugins.ts +19 -0
- package/src/serverEntry.ts +95 -0
- package/template/bunfig.toml +4 -0
- package/template/package.json +18 -0
- package/template/src/app.ts +28 -0
- package/template/src/bundle/icon.png +0 -0
- package/template/src/cli/banner.txt +3 -0
- package/template/src/cli/footer.txt +1 -0
- package/template/src/server/config.ts +17 -0
- package/template/src/server/rpc/getHello.ts +36 -0
- package/template/src/ui/Layout.abide +19 -0
- package/template/src/ui/app.css +21 -0
- package/template/src/ui/app.html +24 -0
- package/template/src/ui/pages/about/page.abide +9 -0
- package/template/src/ui/pages/page.abide +22 -0
- package/template/test/app.test.ts +30 -0
- package/template/tsconfig.json +18 -0
- package/tsconfig.app.json +17 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
The signal binding names a `<script>` nested in a control-flow branch declares
|
|
5
|
+
(`state`/`derived`/`prop`). The back-end adds them to the deref scope so both the
|
|
6
|
+
script body and the branch's markup rewrite `{a}` → `a.value` — these stay PLAIN
|
|
7
|
+
signals (local to the branch's render, owned by its scope, re-seeded from the
|
|
8
|
+
in-scope data each mount), unlike the top-level component script which desugars to
|
|
9
|
+
the serializable `doc`.
|
|
10
|
+
*/
|
|
11
|
+
export function nestedBindingNames(code: string): Set<string> {
|
|
12
|
+
const source = ts.createSourceFile('nested.ts', code, ts.ScriptTarget.Latest, true)
|
|
13
|
+
const names = new Set<string>()
|
|
14
|
+
for (const statement of source.statements) {
|
|
15
|
+
if (!ts.isVariableStatement(statement)) {
|
|
16
|
+
continue
|
|
17
|
+
}
|
|
18
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
19
|
+
const callee = signalCallee(declaration)
|
|
20
|
+
if (
|
|
21
|
+
(callee === 'state' || callee === 'derived' || callee === 'prop') &&
|
|
22
|
+
ts.isIdentifier(declaration.name)
|
|
23
|
+
) {
|
|
24
|
+
names.add(declaration.name.text)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return names
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* The callee name of a `NAME = state(...)` / `derived(...)` / `prop(...)` declaration. */
|
|
32
|
+
function signalCallee(declaration: ts.VariableDeclaration): string | undefined {
|
|
33
|
+
const initializer = declaration.initializer
|
|
34
|
+
if (
|
|
35
|
+
initializer !== undefined &&
|
|
36
|
+
ts.isCallExpression(initializer) &&
|
|
37
|
+
ts.isIdentifier(initializer.expression)
|
|
38
|
+
) {
|
|
39
|
+
return initializer.expression.text
|
|
40
|
+
}
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ShadowMapping } from './types/CompiledShadow.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Relocates a diagnostic's shadow span back to the original `.abide` source. The
|
|
5
|
+
diagnostic must *overlap* a mapped segment (a verbatim-emitted expression);
|
|
6
|
+
diagnostics confined to synthesised scaffolding overlap nothing and are dropped —
|
|
7
|
+
that is the filter that keeps shadow-internal noise out of the editor. Overlap
|
|
8
|
+
(not containment) is required because TypeScript often reports a whole-expression
|
|
9
|
+
mismatch at the synthetic wrapping `(`, one char before the mapped span; the
|
|
10
|
+
result is clamped into the segment so it lands on real source either way.
|
|
11
|
+
*/
|
|
12
|
+
export function remapShadowDiagnostic(
|
|
13
|
+
mappings: ShadowMapping[],
|
|
14
|
+
shadowStart: number,
|
|
15
|
+
shadowLength: number,
|
|
16
|
+
): { start: number; length: number } | undefined {
|
|
17
|
+
const shadowEnd = shadowStart + Math.max(shadowLength, 1)
|
|
18
|
+
const mapping = mappings.find(
|
|
19
|
+
(entry) => shadowStart < entry.shadowStart + entry.length && entry.shadowStart < shadowEnd,
|
|
20
|
+
)
|
|
21
|
+
if (mapping === undefined) {
|
|
22
|
+
return undefined
|
|
23
|
+
}
|
|
24
|
+
const clampedStart = Math.max(shadowStart, mapping.shadowStart)
|
|
25
|
+
const segmentEnd = mapping.shadowStart + mapping.length
|
|
26
|
+
return {
|
|
27
|
+
start: mapping.sourceStart + (clampedStart - mapping.shadowStart),
|
|
28
|
+
length: Math.max(1, Math.min(shadowEnd, segmentEnd) - clampedStart),
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Rewrites references to a component's signal bindings into the document form the
|
|
5
|
+
rest of the pipeline understands: a `state` binding `count` becomes `model.count`
|
|
6
|
+
(data access `lowerDocAccess` then lowers to a patch/read), and a `derived`
|
|
7
|
+
binding `total` becomes `total.value`. Only value-position identifiers are
|
|
8
|
+
touched — declaration names, parameter names, and property names are collected
|
|
9
|
+
into a skip set first, and object shorthand (`{ count }`) is expanded to
|
|
10
|
+
`{ count: model.count }`. This is the bridge from the signal surface the author
|
|
11
|
+
writes to the patch substrate underneath.
|
|
12
|
+
*/
|
|
13
|
+
export function renameSignalRefs(
|
|
14
|
+
code: string,
|
|
15
|
+
stateNames: ReadonlySet<string>,
|
|
16
|
+
derivedNames: ReadonlySet<string>,
|
|
17
|
+
): string {
|
|
18
|
+
const source = ts.createSourceFile('component.ts', code, ts.ScriptTarget.Latest, true)
|
|
19
|
+
|
|
20
|
+
/* Identifier nodes that are names, not value reads — never rewritten. */
|
|
21
|
+
const skip = new Set<ts.Node>()
|
|
22
|
+
const collect = (node: ts.Node): void => {
|
|
23
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
24
|
+
skip.add(node.name)
|
|
25
|
+
}
|
|
26
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
|
|
27
|
+
skip.add(node.name)
|
|
28
|
+
}
|
|
29
|
+
if (ts.isParameter(node) && ts.isIdentifier(node.name)) {
|
|
30
|
+
skip.add(node.name)
|
|
31
|
+
}
|
|
32
|
+
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
|
|
33
|
+
skip.add(node.name)
|
|
34
|
+
}
|
|
35
|
+
if (
|
|
36
|
+
(ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) &&
|
|
37
|
+
node.name !== undefined
|
|
38
|
+
) {
|
|
39
|
+
skip.add(node.name)
|
|
40
|
+
}
|
|
41
|
+
ts.forEachChild(node, collect)
|
|
42
|
+
}
|
|
43
|
+
collect(source)
|
|
44
|
+
|
|
45
|
+
const result = ts.transform(source, [
|
|
46
|
+
(context) => (root) => {
|
|
47
|
+
const visit = (node: ts.Node): ts.Node => {
|
|
48
|
+
/* Shorthand `{ count }` → `{ count: model.count }` / `{ total: total.value }`. */
|
|
49
|
+
if (ts.isShorthandPropertyAssignment(node)) {
|
|
50
|
+
const replacement = referenceFor(node.name.text, stateNames, derivedNames)
|
|
51
|
+
if (replacement !== undefined) {
|
|
52
|
+
return ts.factory.createPropertyAssignment(node.name.text, replacement)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (ts.isIdentifier(node) && !skip.has(node)) {
|
|
56
|
+
const replacement = referenceFor(node.text, stateNames, derivedNames)
|
|
57
|
+
if (replacement !== undefined) {
|
|
58
|
+
return replacement
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return ts.visitEachChild(node, visit, context)
|
|
62
|
+
}
|
|
63
|
+
return ts.visitNode(root, visit) as ts.SourceFile
|
|
64
|
+
},
|
|
65
|
+
])
|
|
66
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed })
|
|
67
|
+
const output = printer.printFile(result.transformed[0] as ts.SourceFile)
|
|
68
|
+
result.dispose()
|
|
69
|
+
return output
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* `model.<name>` for a state binding, `<name>.value` for a derived one, else undefined. */
|
|
73
|
+
function referenceFor(
|
|
74
|
+
name: string,
|
|
75
|
+
stateNames: ReadonlySet<string>,
|
|
76
|
+
derivedNames: ReadonlySet<string>,
|
|
77
|
+
): ts.Expression | undefined {
|
|
78
|
+
if (stateNames.has(name)) {
|
|
79
|
+
return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('model'), name)
|
|
80
|
+
}
|
|
81
|
+
if (derivedNames.has(name)) {
|
|
82
|
+
return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(name), 'value')
|
|
83
|
+
}
|
|
84
|
+
return undefined
|
|
85
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path'
|
|
2
|
+
import ts from 'typescript'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
A module-name resolver shared by the shadow Program (check) and LanguageService
|
|
6
|
+
(LSP). A relative `./X.abide` import resolves directly to its virtual shadow
|
|
7
|
+
`./X.abide.ts` (the host serves shadow text for any `*.abide.ts` name), so
|
|
8
|
+
cross-component prop checking works. An aliased `.abide` (`$ui/X.abide`) falls
|
|
9
|
+
through to TypeScript's own resolver, which applies the tsconfig `paths` and —
|
|
10
|
+
because the host reports the shadow `.abide.ts` exists — lands on the same
|
|
11
|
+
shadow. Every other specifier (`abide/*`, `$server/*`, plain relative `.ts`,
|
|
12
|
+
asset modules covered by the ambient declarations) resolves through TypeScript
|
|
13
|
+
directly, exactly as for the real module.
|
|
14
|
+
*/
|
|
15
|
+
export function resolveAbideImports(
|
|
16
|
+
options: ts.CompilerOptions,
|
|
17
|
+
host: ts.ModuleResolutionHost,
|
|
18
|
+
): (moduleNames: string[], containingFile: string) => (ts.ResolvedModule | undefined)[] {
|
|
19
|
+
return (moduleNames, containingFile) =>
|
|
20
|
+
moduleNames.map((name) => {
|
|
21
|
+
if (name.endsWith('.abide')) {
|
|
22
|
+
const relative = resolve(dirname(containingFile), name)
|
|
23
|
+
if (ts.sys.fileExists(relative)) {
|
|
24
|
+
return { resolvedFileName: `${relative}.ts`, extension: ts.Extension.Ts }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return ts.resolveModuleName(name, containingFile, options, host).resolvedModule
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Scopes a component's CSS to its own elements by appending an attribute selector
|
|
3
|
+
(`[data-a-<hash>]`) to each rule's key compound selector — the proven approach
|
|
4
|
+
(every element the component renders carries the attribute, so descendant
|
|
5
|
+
selectors still resolve, but styles never leak out). At-rule preludes (`@media`,
|
|
6
|
+
etc.) pass through untouched while the nested rules inside them are still scoped.
|
|
7
|
+
The attribute is inserted before any pseudo (`a:hover` → `a[attr]:hover`) so the
|
|
8
|
+
selector stays valid.
|
|
9
|
+
*/
|
|
10
|
+
export function scopeCss(css: string, attribute: string): string {
|
|
11
|
+
let result = ''
|
|
12
|
+
let prelude = '' // chars accumulated since the last brace
|
|
13
|
+
let depth = 0
|
|
14
|
+
let keyframesDepth = -1 // brace depth of the open @keyframes block, or -1 when outside one
|
|
15
|
+
for (const char of css) {
|
|
16
|
+
if (char === '{') {
|
|
17
|
+
const insideKeyframes = keyframesDepth !== -1 && depth >= keyframesDepth
|
|
18
|
+
if (prelude.trim().startsWith('@')) {
|
|
19
|
+
/* At-rule prelude: leave it; its inner rules scope on their own. A
|
|
20
|
+
@keyframes block is the exception — its `from`/`to`/`%` steps aren't
|
|
21
|
+
selectors, so track its depth and leave the steps inside it bare. */
|
|
22
|
+
if (/^@(-[a-z]+-)?keyframes\b/i.test(prelude.trim())) {
|
|
23
|
+
keyframesDepth = depth + 1
|
|
24
|
+
}
|
|
25
|
+
result += `${prelude}{`
|
|
26
|
+
} else if (insideKeyframes) {
|
|
27
|
+
result += `${prelude}{` // a keyframe step (from/to/%) — not a selector
|
|
28
|
+
} else {
|
|
29
|
+
result += `${scopeSelectorList(prelude, attribute)} {`
|
|
30
|
+
}
|
|
31
|
+
depth += 1
|
|
32
|
+
prelude = ''
|
|
33
|
+
} else if (char === '}') {
|
|
34
|
+
result += `${prelude}}`
|
|
35
|
+
prelude = ''
|
|
36
|
+
depth -= 1
|
|
37
|
+
if (keyframesDepth !== -1 && depth < keyframesDepth) {
|
|
38
|
+
keyframesDepth = -1
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
prelude += char
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result + prelude
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Scopes each selector in a comma-separated list, splitting at top-level commas
|
|
48
|
+
only so a `,` inside `:is(.a, .b)` / `[attr=","]` doesn't fragment a selector. */
|
|
49
|
+
function scopeSelectorList(prelude: string, attribute: string): string {
|
|
50
|
+
return splitSelectorList(prelude)
|
|
51
|
+
.map((selector) => scopeSelector(selector.trim(), attribute))
|
|
52
|
+
.join(', ')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Splits a selector list on commas that aren't nested inside `()` or `[]`. */
|
|
56
|
+
function splitSelectorList(prelude: string): string[] {
|
|
57
|
+
const selectors: string[] = []
|
|
58
|
+
let current = ''
|
|
59
|
+
let nesting = 0
|
|
60
|
+
for (const char of prelude) {
|
|
61
|
+
if (char === '(' || char === '[') {
|
|
62
|
+
nesting += 1
|
|
63
|
+
} else if (char === ')' || char === ']') {
|
|
64
|
+
nesting -= 1
|
|
65
|
+
}
|
|
66
|
+
if (char === ',' && nesting === 0) {
|
|
67
|
+
selectors.push(current)
|
|
68
|
+
current = ''
|
|
69
|
+
} else {
|
|
70
|
+
current += char
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
selectors.push(current)
|
|
74
|
+
return selectors
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Appends `[attribute]` to a selector's last compound, before any pseudo. */
|
|
78
|
+
function scopeSelector(selector: string, attribute: string): string {
|
|
79
|
+
if (selector === '') {
|
|
80
|
+
return selector
|
|
81
|
+
}
|
|
82
|
+
const match = selector.match(/^(.*?)([^\s>+~]+)$/)
|
|
83
|
+
if (match === null) {
|
|
84
|
+
return `${selector}[${attribute}]`
|
|
85
|
+
}
|
|
86
|
+
const prefix = match[1] ?? ''
|
|
87
|
+
const last = match[2] ?? ''
|
|
88
|
+
const pseudo = pseudoIndex(last)
|
|
89
|
+
const scopedLast =
|
|
90
|
+
pseudo === -1
|
|
91
|
+
? `${last}[${attribute}]`
|
|
92
|
+
: `${last.slice(0, pseudo)}[${attribute}]${last.slice(pseudo)}`
|
|
93
|
+
return `${prefix}${scopedLast}`
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/*
|
|
97
|
+
Index of the first pseudo-class/element colon in a compound — i.e. a `:` at
|
|
98
|
+
bracket depth zero. Skips colons inside an attribute selector's value
|
|
99
|
+
(e.g. `a[href='http://x']`), which must not be treated as a pseudo boundary.
|
|
100
|
+
Returns -1 when the compound has no pseudo.
|
|
101
|
+
*/
|
|
102
|
+
function pseudoIndex(compound: string): number {
|
|
103
|
+
let depth = 0
|
|
104
|
+
for (let index = 0; index < compound.length; index += 1) {
|
|
105
|
+
const char = compound[index]
|
|
106
|
+
if (char === '[') {
|
|
107
|
+
depth += 1
|
|
108
|
+
} else if (char === ']') {
|
|
109
|
+
depth -= 1
|
|
110
|
+
} else if (char === ':' && depth === 0) {
|
|
111
|
+
return index
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return -1
|
|
115
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
A `.abide` component's virtual shadow is the same absolute path with `.ts`
|
|
3
|
+
appended (`Foo.abide` → `Foo.abide.ts`). The suffix lets a TypeScript host tell a
|
|
4
|
+
shadow apart from a real file and recover the source path. Shared by the one-shot
|
|
5
|
+
Program (`createShadowProgram`) and the incremental LanguageService (the LSP).
|
|
6
|
+
*/
|
|
7
|
+
export const shadowNaming = {
|
|
8
|
+
suffixed: (abidePath: string): string => `${abidePath}.ts`,
|
|
9
|
+
isShadow: (fileName: string): boolean => fileName.endsWith('.abide.ts'),
|
|
10
|
+
sourceOf: (shadowName: string): string => shadowName.slice(0, -'.ts'.length),
|
|
11
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ShadowMapping } from './types/CompiledShadow.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Translates an offset in the original `.abide` source to the equivalent offset in
|
|
5
|
+
its type-checking shadow — the inverse of `remapShadowDiagnostic`. Drives
|
|
6
|
+
position-based language-service queries (hover, completion, …) from an editor
|
|
7
|
+
position: find the verbatim-emitted segment whose source span covers the offset
|
|
8
|
+
and shift it into shadow coordinates. An offset outside every mapped span
|
|
9
|
+
(whitespace, markup, framework syntax the shadow doesn't emit verbatim) has no
|
|
10
|
+
shadow position, so the query is skipped.
|
|
11
|
+
*/
|
|
12
|
+
export function sourceToShadowOffset(
|
|
13
|
+
mappings: ShadowMapping[],
|
|
14
|
+
sourceOffset: number,
|
|
15
|
+
): number | undefined {
|
|
16
|
+
const mapping = mappings.find(
|
|
17
|
+
(entry) =>
|
|
18
|
+
entry.sourceStart <= sourceOffset && sourceOffset < entry.sourceStart + entry.length,
|
|
19
|
+
)
|
|
20
|
+
if (mapping === undefined) {
|
|
21
|
+
return undefined
|
|
22
|
+
}
|
|
23
|
+
return mapping.shadowStart + (sourceOffset - mapping.sourceStart)
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TemplateNode } from './types/TemplateNode.ts'
|
|
2
|
+
|
|
3
|
+
/* The value of a static attribute on an element node, or undefined when absent.
|
|
4
|
+
Used to read directive attributes like `slot` / `slot name` off the template. */
|
|
5
|
+
export function staticAttrValue(
|
|
6
|
+
node: Extract<TemplateNode, { kind: 'element' }>,
|
|
7
|
+
name: string,
|
|
8
|
+
): string | undefined {
|
|
9
|
+
const attr = node.attrs.find(
|
|
10
|
+
(candidate) => candidate.kind === 'static' && candidate.name === name,
|
|
11
|
+
)
|
|
12
|
+
return attr !== undefined && attr.kind === 'static' ? attr.value : undefined
|
|
13
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Removes `effect(...)` calls from a script for the SSR back-end. Effects are client
|
|
5
|
+
lifecycle — they touch the DOM / run side effects and emit no HTML, so the server
|
|
6
|
+
render (a snapshot of the pre-effect markup, like every framework) must not run
|
|
7
|
+
them. Every `effect(<args>)` call is replaced by `undefined`, dropping its body:
|
|
8
|
+
an `effect(() => …)` statement becomes a no-op, and a `const stop = effect(…)`
|
|
9
|
+
binding keeps a defined (unused) name. Client compilation keeps effects untouched.
|
|
10
|
+
*/
|
|
11
|
+
export function stripEffects(code: string): string {
|
|
12
|
+
const source = ts.createSourceFile('script.ts', code, ts.ScriptTarget.Latest, true)
|
|
13
|
+
const result = ts.transform(source, [
|
|
14
|
+
(context) => (root) => {
|
|
15
|
+
const visit = (node: ts.Node): ts.Node => {
|
|
16
|
+
if (
|
|
17
|
+
ts.isCallExpression(node) &&
|
|
18
|
+
ts.isIdentifier(node.expression) &&
|
|
19
|
+
node.expression.text === 'effect'
|
|
20
|
+
) {
|
|
21
|
+
return ts.factory.createIdentifier('undefined')
|
|
22
|
+
}
|
|
23
|
+
return ts.visitEachChild(node, visit, context)
|
|
24
|
+
}
|
|
25
|
+
return ts.visitNode(root, visit) as ts.SourceFile
|
|
26
|
+
},
|
|
27
|
+
])
|
|
28
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed })
|
|
29
|
+
const output = printer.printFile(result.transformed[0] as ts.SourceFile)
|
|
30
|
+
result.dispose()
|
|
31
|
+
return output
|
|
32
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
A type-check diagnostic relocated onto a `.abide` source file: `start`/`length`
|
|
5
|
+
are an offset range in the original component file (not the shadow), ready for a
|
|
6
|
+
CLI to render or the LSP to convert to a line/character range.
|
|
7
|
+
*/
|
|
8
|
+
export type AbideDiagnostic = {
|
|
9
|
+
file: string
|
|
10
|
+
start: number
|
|
11
|
+
length: number
|
|
12
|
+
message: string
|
|
13
|
+
category: ts.DiagnosticCategory
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TemplateNode } from './TemplateNode.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
The shared front-end result for a component, consumed by both the client
|
|
5
|
+
(`generateBuild`) and server (`generateSSR`) code generators: the lowered script
|
|
6
|
+
(signal surface desugared to the doc patch/read API), the signal binding names
|
|
7
|
+
(so template expressions rewrite consistently), and the parsed template tree.
|
|
8
|
+
*/
|
|
9
|
+
export type AnalyzedComponent = {
|
|
10
|
+
script: string
|
|
11
|
+
/* Top-level import statements hoisted out of the script (e.g. child
|
|
12
|
+
components), placed at module scope by the module wrapper. */
|
|
13
|
+
imports: string
|
|
14
|
+
stateNames: Set<string>
|
|
15
|
+
derivedNames: Set<string>
|
|
16
|
+
nodes: TemplateNode[]
|
|
17
|
+
/* One entry per non-empty `<style>` in the template (in source order): the scope
|
|
18
|
+
attribute its covered elements carry (annotated onto `nodes`) and the scoped
|
|
19
|
+
CSS to bundle. A top-level `<style>` covers the whole component; a nested one
|
|
20
|
+
covers only its sibling subtree. Empty for a component with no style. */
|
|
21
|
+
styles: { attribute: string; css: string }[]
|
|
22
|
+
/* False when the template contains an `await` block (not adoptable yet) — the
|
|
23
|
+
router mounts (re-renders) rather than hydrates such a page. */
|
|
24
|
+
hydratable: boolean
|
|
25
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
The type-checking shadow of a `.abide` component: a synthetic `.ts` module that
|
|
3
|
+
reconstructs the author-facing scope with value types and references every
|
|
4
|
+
template expression in a checkable position, plus the segment map that relocates
|
|
5
|
+
a diagnostic in the shadow back to the original `.abide` source.
|
|
6
|
+
|
|
7
|
+
Each mapping covers one verbatim-emitted span: `length` characters at `shadowStart`
|
|
8
|
+
in the shadow correspond to the same `length` characters at `sourceStart` in the
|
|
9
|
+
`.abide` file (expressions are emitted unchanged, so the spans are equal length).
|
|
10
|
+
A shadow offset inside a mapping translates to `sourceStart + (offset - shadowStart)`;
|
|
11
|
+
an offset in no mapping is synthesised scaffolding and its diagnostic is dropped.
|
|
12
|
+
*/
|
|
13
|
+
export type ShadowMapping = { shadowStart: number; sourceStart: number; length: number }
|
|
14
|
+
|
|
15
|
+
export type CompiledShadow = { code: string; mappings: ShadowMapping[] }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
An element attribute. `static` is a literal; `expression` is `name={code}` bound
|
|
3
|
+
reactively; `event` is `on<event>={code}` where `code` evaluates to the handler;
|
|
4
|
+
`bind` is `bind:<property>={lvalue}`, a two-way binding whose `code` is the
|
|
5
|
+
writable doc path read into the property and written back on input; `attach` is
|
|
6
|
+
`attach={code}` where `code` evaluates to an attachment `(node) => teardown` run
|
|
7
|
+
at build with node-lifetime teardown. `loc` is the
|
|
8
|
+
absolute offset of `code` in the original `.abide` source (see TextPart) —
|
|
9
|
+
optional, set only when the parser tracks positions for the type-checking shadow.
|
|
10
|
+
*/
|
|
11
|
+
export type TemplateAttr =
|
|
12
|
+
| { kind: 'static'; name: string; value: string }
|
|
13
|
+
| { kind: 'expression'; name: string; code: string; loc?: number }
|
|
14
|
+
| { kind: 'event'; event: string; code: string; loc?: number }
|
|
15
|
+
| { kind: 'bind'; property: string; code: string; loc?: number }
|
|
16
|
+
| { kind: 'attach'; code: string; loc?: number }
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { TemplateAttr } from './TemplateAttr.ts'
|
|
2
|
+
import type { TextPart } from './TextPart.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
A parsed template node. `text` carries interpolation parts; `element` carries
|
|
6
|
+
attributes and children; `each` is the `<template each as key>` control flow over
|
|
7
|
+
a list. (if/await/switch are future siblings.)
|
|
8
|
+
|
|
9
|
+
`loc` (where present) is the absolute offset of the node's primary expression in
|
|
10
|
+
the original `.abide` source — additive, set only when the parser tracks
|
|
11
|
+
positions for the type-checking shadow, ignored by the runtime back-ends.
|
|
12
|
+
*/
|
|
13
|
+
export type TemplateNode =
|
|
14
|
+
| { kind: 'text'; parts: TextPart[] }
|
|
15
|
+
| { kind: 'script'; code: string }
|
|
16
|
+
/* A `<style>` declared in the template. `css` is its raw body, read structurally
|
|
17
|
+
so a `<style>` inside an expression isn't mistaken for one. The node stays in
|
|
18
|
+
place: it scopes its sibling subtree, so the front-end derives each scope
|
|
19
|
+
attribute and the elements it covers from the node's position (see
|
|
20
|
+
`analyzeComponent`). Emits no DOM/markup. */
|
|
21
|
+
| { kind: 'style'; css: string }
|
|
22
|
+
| {
|
|
23
|
+
kind: 'element'
|
|
24
|
+
tag: string
|
|
25
|
+
attrs: TemplateAttr[]
|
|
26
|
+
children: TemplateNode[]
|
|
27
|
+
/* The scope attributes (`data-a-…`) this element carries — one per `<style>`
|
|
28
|
+
active at its position (its own sibling list plus every ancestor's),
|
|
29
|
+
filled by `analyzeComponent`. Absent until annotated. */
|
|
30
|
+
scopes?: string[]
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
kind: 'each'
|
|
34
|
+
items: string
|
|
35
|
+
as: string
|
|
36
|
+
key: string | undefined
|
|
37
|
+
/* `await` on the tag → `items` is an AsyncIterable, drained on the client. */
|
|
38
|
+
async: boolean
|
|
39
|
+
children: TemplateNode[]
|
|
40
|
+
loc?: number
|
|
41
|
+
}
|
|
42
|
+
| { kind: 'if'; condition: string; children: TemplateNode[]; loc?: number }
|
|
43
|
+
| {
|
|
44
|
+
kind: 'await'
|
|
45
|
+
promise: string
|
|
46
|
+
/* `then` riding the `await` tag (`<template await={p} then={v}>`) makes the
|
|
47
|
+
block BLOCKING: no pending branch, children are the resolved content bound
|
|
48
|
+
to `as`, SSR settles before the first flush. Absent → streaming. */
|
|
49
|
+
blocking: boolean
|
|
50
|
+
as: string | undefined
|
|
51
|
+
children: TemplateNode[]
|
|
52
|
+
loc?: number
|
|
53
|
+
}
|
|
54
|
+
| { kind: 'try'; children: TemplateNode[] }
|
|
55
|
+
| {
|
|
56
|
+
kind: 'branch'
|
|
57
|
+
branch: 'then' | 'catch' | 'finally'
|
|
58
|
+
as: string | undefined
|
|
59
|
+
children: TemplateNode[]
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
kind: 'component'
|
|
63
|
+
name: string
|
|
64
|
+
props: { name: string; code: string; loc?: number }[]
|
|
65
|
+
children: TemplateNode[]
|
|
66
|
+
}
|
|
67
|
+
| { kind: 'switch'; subject: string; children: TemplateNode[]; loc?: number }
|
|
68
|
+
| { kind: 'case'; match: string | undefined; children: TemplateNode[]; loc?: number }
|
|
69
|
+
/* A `<template name="row" args={item}>` snippet: a named, scope-capturing
|
|
70
|
+
builder declared once and called like a function (`{row(item)}`). `params`
|
|
71
|
+
is the raw `args` source spliced into the builder's parameter list. */
|
|
72
|
+
| {
|
|
73
|
+
kind: 'snippet'
|
|
74
|
+
name: string
|
|
75
|
+
params: string | undefined
|
|
76
|
+
children: TemplateNode[]
|
|
77
|
+
loc?: number
|
|
78
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/* A piece of a text node: literal characters, or a `{expr}` interpolation whose
|
|
2
|
+
`code` is lowered and bound reactively. `loc` is the absolute offset of the
|
|
3
|
+
expression's first character in the original `.abide` source — present only
|
|
4
|
+
when the parser was given the source's base offset; the runtime back-ends
|
|
5
|
+
ignore it, the type-checking shadow maps diagnostics through it. */
|
|
6
|
+
export type TextPart =
|
|
7
|
+
| { kind: 'static'; value: string }
|
|
8
|
+
| { kind: 'expression'; code: string; loc?: number }
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createComputedNode } from './runtime/createComputedNode.ts'
|
|
2
|
+
import { OWNER } from './runtime/OWNER.ts'
|
|
3
|
+
import { readNode } from './runtime/readNode.ts'
|
|
4
|
+
import type { Derived } from './runtime/types/Derived.ts'
|
|
5
|
+
import { unlinkDeps } from './runtime/unlinkDeps.ts'
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
A read-only reactive cell computed from other cells — the abide replacement for
|
|
9
|
+
`$derived`. Lazy: it recomputes on read only when a dependency has changed, and
|
|
10
|
+
never serializes (it is re-derived from its inputs on resume). Read via `.value`.
|
|
11
|
+
*/
|
|
12
|
+
// @readme plumbing
|
|
13
|
+
export function derived<T>(compute: () => T): Derived<T> {
|
|
14
|
+
const node = createComputedNode(compute as () => unknown)
|
|
15
|
+
/* Tear down with the enclosing scope, the way an effect does. A computed only
|
|
16
|
+
unlinks from its sources when it re-runs (`runNode` re-tracking); one read
|
|
17
|
+
once and then abandoned never re-runs, so absent this it would sit in its
|
|
18
|
+
source signals' subscriber lists forever — re-marked dirty on every write to
|
|
19
|
+
them — for the source's lifetime. Outside a scope it owns its own life (no-op). */
|
|
20
|
+
if (OWNER.current !== undefined) {
|
|
21
|
+
OWNER.current.push(() => unlinkDeps(node))
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
get value(): T {
|
|
25
|
+
return readNode(node) as T
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createDoc } from './runtime/createDoc.ts'
|
|
2
|
+
import type { Doc } from './runtime/types/Doc.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Creates a reactive document: a single immutable, serializable tree addressed by
|
|
6
|
+
path, where every change is a patch. `doc.read(path)` is path-granular reactive
|
|
7
|
+
read; `doc.replace/add/remove` emit patches that wake only the readers whose
|
|
8
|
+
paths the change touched. This is the substrate the whole framework stands on —
|
|
9
|
+
deep reactivity, resumability, undo, and sync all reduce to "a patch over a
|
|
10
|
+
path", so they share one mechanism instead of being bolted on.
|
|
11
|
+
*/
|
|
12
|
+
// @readme plumbing
|
|
13
|
+
export function doc(initial: unknown = {}): Doc {
|
|
14
|
+
return createDoc(initial)
|
|
15
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { snippetPayload } from '../../shared/snippet.ts'
|
|
2
|
+
import { claimChild } from '../runtime/claimChild.ts'
|
|
3
|
+
import { RENDER } from '../runtime/RENDER.ts'
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
A `{snippet(args)}` interpolation: mount the branded builder's nodes at this
|
|
7
|
+
position. The builder builds straight into `parent` — sequential build order
|
|
8
|
+
places it correctly among siblings, and its effects join the surrounding
|
|
9
|
+
component scope (so they tear down with it). The body's reactive reads update
|
|
10
|
+
fine-grained via those effects; an enclosing `each` re-mounts on list changes.
|
|
11
|
+
|
|
12
|
+
On hydrate the builder runs against the server-rendered nodes between the
|
|
13
|
+
`<!--abide:snippet-->`/`<!--/abide:snippet-->` markers — its `openChild`/`appendText`
|
|
14
|
+
claim them in place. The cursor is advanced past the open marker before, and past
|
|
15
|
+
the close marker after, so the markers themselves are skipped.
|
|
16
|
+
*/
|
|
17
|
+
// @readme plumbing
|
|
18
|
+
export function appendSnippet(parent: Node, read: () => unknown): void {
|
|
19
|
+
const builder = snippetPayload(read())
|
|
20
|
+
if (typeof builder !== 'function') {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
const mount = builder as (host: Node) => void
|
|
24
|
+
const hydration = RENDER.hydration
|
|
25
|
+
if (hydration !== undefined) {
|
|
26
|
+
const open = claimChild(hydration, parent)
|
|
27
|
+
hydration.next.set(parent, open === null ? null : open.nextSibling)
|
|
28
|
+
mount(parent)
|
|
29
|
+
const close = claimChild(hydration, parent)
|
|
30
|
+
hydration.next.set(parent, close === null ? null : close.nextSibling)
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
mount(parent)
|
|
34
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { claimChild } from '../runtime/claimChild.ts'
|
|
2
|
+
import { RENDER } from '../runtime/RENDER.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
A static (non-reactive) text node under `parent`: created and appended (create
|
|
6
|
+
mode), or claimed from the server-rendered text (hydrate mode). As with reactive
|
|
7
|
+
text, a merged SSR text node is split at this literal's length so the next claim
|
|
8
|
+
lines up; nothing is bound since the text never changes.
|
|
9
|
+
*/
|
|
10
|
+
// @readme plumbing
|
|
11
|
+
export function appendStatic(parent: Node, value: string, splitAlways = false): void {
|
|
12
|
+
const hydration = RENDER.hydration
|
|
13
|
+
if (hydration !== undefined) {
|
|
14
|
+
const node = claimChild(hydration, parent) as unknown as Text
|
|
15
|
+
/* Split even on an exact-length consume when a sibling text binding follows
|
|
16
|
+
(`splitAlways`), so it gets its own node; see appendText for the rationale. */
|
|
17
|
+
if (
|
|
18
|
+
node !== null &&
|
|
19
|
+
(splitAlways ? value.length <= node.data.length : value.length < node.data.length)
|
|
20
|
+
) {
|
|
21
|
+
node.splitText(value.length)
|
|
22
|
+
}
|
|
23
|
+
hydration.next.set(parent, node === null ? null : node.nextSibling)
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
parent.appendChild(document.createTextNode(value))
|
|
27
|
+
}
|