f3c175436af55c201f1373fffa693a1dc0ad2c34
treeToState had no resolvedName allowlist, so an AI `replace` response (scope site/page/header/footer, reaches this function via actions.deserialize with no further validation downstream) containing an unknown component could produce a state that throws at deserialize/render. Extract the core transform into standalone treeToCraftState (directly unit-testable without mounting a Craft.js Editor), route it through sanitizeAiTree for the same resolvedName allowlist + id/ROOT repair buildNodeTree already had, and fall back to the empty canvas if the tree's own root is invalid. Delegate the structural walk to the shared flattenTreeForCraft extracted in the previous commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Description
Visual drag-and-drop website builder using GrapesJS
Languages
TypeScript
61.2%
HTML
17.1%
JavaScript
17%
CSS
3.6%
PHP
0.8%
Other
0.3%