import { join } from "node:path"; import { rmSync } from "node:fs"; import { writeText } from "../util/fsx.js"; import type { IR, IRNode, IRChild, IRTextNode, StyleMap } from "../normalize/ir.js"; import { isTextChild } from "../normalize/ir.js"; import { generateCss, RESET_CSS } from "./css.js"; import { generateInteractionCss } from "./interactionCss.js"; import { buildRuntimeSpecs, wiresJsx, dittoWireImportPath, DITTO_WIRE_TSX, accordionJsx, accordionImportPath, ACCORDION_TSX, type AccordionRuntimeSpec, type RuntimeSpec } from "./interactive.js"; import { buildMotionSpec, motionWireJsx, dittoMotionImportPath, motionHasContent, DITTO_MOTION_TSX, type MotionSpec } from "./motion.js"; import { buildLottieSpec, lottieWireJsx, dittoLottieImportPath, lottieHasContent, DITTO_LOTTIE_TSX, type LottieSpec as LottieRuntimeSpec } from "./lottie.js"; import { buildMenuSpecs, menusJsx, dropdownMenuImportPath, DROPDOWN_MENU_TSX, type RTMenu } from "./menu.js"; import type { AssetGraph } from "../infer/assets.js"; import type { FontGraph } from "../infer/fonts.js"; import { SYSTEM_FALLBACK } from "../infer/fonts.js"; import { detectComponents, type ComponentPlan, type ComponentCluster } from "../infer/components.js"; import { buildClassMap } from "./classMap.js"; import { buildTailwind, tailwindGlobalsCss } from "./tailwind.js"; import { planSections, type SectionPlan } from "./sectionSplit.js"; import type { RecipeReport } from "../infer/recipes.js"; import { emitSeoAssetFiles, emitSeoRoutes, jsonLdHeadMarkup, metadataExport, routeSummaryFromIr, seoStaticFiles, siteOriginImportLine, SITE_ORIGIN_LAYOUT_IMPORT, SITE_ORIGIN_MODULE, viewportExport, type SeoInventory } from "./seo.js"; import { emitGeneratedDocs } from "./docs.js"; const VOID_TAGS = new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]); // Containers whose only valid children are specific elements; the HTML parser // foster-parents stray (whitespace) text out, so emitting it breaks hydration. const ELEMENT_ONLY_PARENTS = new Set(["ul", "ol", "table", "thead", "tbody", "tfoot", "tr", "select", "colgroup", "optgroup", "menu", "dl"]); // Block-level element tags. A JS-built DOM (createElement+appendChild) can legally // place these inside a
/ /. A live React app can create them anywhere
// via the DOM API (so the captured DOM may hold an orphan
/ /…), but when we
// emit one as STATIC HTML with no ancestor the parser foster-parents/drops it, so the
// SSR markup parses to a different tree than React expects → hydration errors #418/#423. Such
// orphans are demoted to a neutral