import { preprocess as sveltePreprocess, type CompileOptions, type PreprocessorGroup } from 'svelte/compiler'; import { render } from 'svelte/server'; import path from 'node:path'; import fs from 'node:fs'; import type { BunPlugin } from 'bun'; import { isSvelteMarker, normalizeAssetPrefix, normalizeIslandHydrationMarkers, relForDisplay, stripHydrationMarkers, toCompileErrorLogs, toPosixPath } from '../utils'; import { injectIslandPropsBlock } from '../islands/islandPropsRegistry'; import { requestContext, renderDetached } from '../runtime/requestContext'; import type { DebugBarData } from '../runtime/requestContext'; import { logger } from '../utils/log'; import { mochiEvents } from '../events'; import { detectHeavyBarrels, formatBarrelLine, formatBarrelSummary, type BarrelMetafile, type HeavyBarrel } from './barrelDetect'; import type { MarkdownConfig, MochiBarrelWarningOptions, MochiManifest, MochiSvelteShakerOptions } from '../types'; import { type HydratableComponent, type PreprocessIslandError, type ServerIslandComponent } from './svelteAstPreprocess'; import { cachedPreprocessHydratable, createPreprocessCacheStats } from './preprocessCache'; import { CompileCache, compileFingerprint, createCompileCacheStats, type CompileCacheStats } from './compileCache'; import { mergeCompilerOptions, type MochiSvelteConfig } from './svelteConfig'; import { backendId, resolveSvelteCompiler, type MochiSvelteCompiler, type SvelteCompilerBackend } from './svelteCompilerBackend'; import { applyFilter } from '../extensions'; import { decodeSourcePath, encodeSourcePath } from './manifestPaths'; import { buildServerOnlyStubModule, scanServerOnlyExports } from './serverOnlyScan'; import { CLIENT_BUILD_DEFINE, serverOnlyModuleGuard } from './serverOnlyModuleGuard'; import { renderMochiEnvServer, renderMochiEnvClient } from './virtualModuleTemplate'; import { createImageAssetLoader, IMAGE_FILE_FILTER } from './imageAssetLoader'; import { EMAIL_TEMPLATE_DIR } from '../email/templates'; import { registerLocalImageAsset } from '../image/localAssetRegistry'; import type { LocalImageAsset } from '../image/types'; import { freshImport } from './freshImport'; import { shakeApp } from './svelteShaker'; import prettyBytes from '../vendor/pretty-bytes'; // The `compile:preprocessors` filter is sync; only applying its preprocessors through Svelte's `preprocess()` is async. async function applyUserPreprocessors(source: string, filename: string, target: 'server' | 'client', development: boolean): Promise { const userPreprocessors: PreprocessorGroup[] = applyFilter('compile:preprocessors', [], { filename, target, development, }); // `builtinTsPreprocessor` runs last so it also strips TS that user preprocessors emit, and it decides TS-ness from the // parsed `attributes` Svelte hands each hook. // // With no user preprocessors, that builtin pass is the only work left and it fires solely on `attributes.lang === 'ts'`. // A `lang="ts"` attribute always contains the literal substring `lang` whatever the quoting, so the gate below can only // false-positive — harmlessly re-parsing a "lang"-containing plain-JS file — and skips the full parse for plain JS. if (userPreprocessors.length === 0 && !source.includes('lang')) { return source; } const result = await sveltePreprocess(source, [...userPreprocessors, builtinTsPreprocessor], { filename }); return result.code; } // Svelte 5's native TS stripping is incomplete — it throws on constructor parameter properties — so Bun's transpiler runs // over `