MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / reactHarness

Function reactHarness

src/artifacts/preview.ts:100–144  ·  view source on GitHub ↗
(src: string)

Source from the content-addressed store, hash-verified

98}
99
100function reactHarness(src: string): string {
101 const code = stripModuleSyntax(src);
102 const comp = detectReactComponent(code);
103 const head =
104 `<script crossorigin src="${CDN.react}"></script>` +
105 `<script crossorigin src="${CDN.reactDom}"></script>` +
106 `<script src="${CDN.babel}"></script>`;
107
108 // We expose the common hooks as bare names (useState, …) for convenience. But if the model's
109 // OWN code already declares any of them — e.g. `const { useState } = React;` or a leftover
110 // `import { useState }` that became a declaration — injecting our destructure too causes
111 // "Identifier 'useState' has already been declared" and the whole render dies. So we only
112 // declare the hooks the model didn't already bring into scope itself.
113 const ALL_HOOKS = ['useState', 'useEffect', 'useRef', 'useMemo', 'useCallback', 'useReducer', 'useContext', 'useLayoutEffect'];
114 const declares = (name: string): boolean => {
115 // `const { … useState … } = React` OR `const useState = …` OR `function useState`
116 const inDestructure = new RegExp(`(?:const|let|var)\\s*\\{[^}]*\\b${name}\\b[^}]*\\}\\s*=`).test(code);
117 const asBinding = new RegExp(`(?:const|let|var|function)\\s+${name}\\b`).test(code);
118 return inDestructure || asBinding;
119 };
120 const hooksToInject = ALL_HOOKS.filter(h => !declares(h));
121 const hookLine = hooksToInject.length
122 ? `const { ${hooksToInject.join(', ')} } = React;\n`
123 : '';
124
125 // The component source + a bootstrap, both transpiled by Babel-in-the-browser.
126 // Mount priority: an `export default` (captured as window.__art_default) wins, else the
127 // detected named component, else a global named `App`. This covers named components,
128 // `export default function Foo`, and anonymous `export default () => …`.
129 const body =
130 `<div id="__art_root"></div>` +
131 `<script type="text/babel" data-presets="react">\n` +
132 hookLine +
133 `${code}\n` +
134 `try {\n` +
135 ` var __Art = (typeof window.__art_default !== 'undefined' && window.__art_default)\n` +
136 ` || (typeof ${comp} !== 'undefined' ? ${comp} : (typeof App !== 'undefined' ? App : null));\n` +
137 ` if (!__Art) throw new Error('No React component found to render (expected a component named ${comp} or a default export).');\n` +
138 ` ReactDOM.createRoot(document.getElementById('__art_root')).render(React.createElement(__Art));\n` +
139 `} catch (e) {\n` +
140 ` document.getElementById('__art_root').innerHTML = '<pre class=\\'__art_text\\'>Render error: ' + (e && e.message) + '</pre>';\n` +
141 `}\n` +
142 `</script>`;
143 return htmlShell(body, head);
144}
145
146function vueHarness(src: string): string {
147 // Use vue3-sfc-loader to render a .vue single-file component straight from source text.

Callers 1

buildPreviewHtmlFunction · 0.85

Calls 4

stripModuleSyntaxFunction · 0.85
detectReactComponentFunction · 0.85
declaresFunction · 0.85
htmlShellFunction · 0.85

Tested by

no test coverage detected