Skip to content

Commit df8a14d

Browse files
committed
add the global and imported scripts to the document per screen
1 parent 252b869 commit df8a14d

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

apps/kitchen-sink/src/ensemble/screens/forms.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,3 +588,6 @@ Global: |
588588
}]
589589
}
590590
}
591+
const sayHello = () => {
592+
window.alert("hello world!");
593+
};

packages/framework/src/hooks/useScreenContext.tsx

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Provider, useAtom, useAtomValue, useSetAtom } from "jotai";
2-
import { useCallback, useContext } from "react";
3-
import { clone, merge } from "lodash-es";
2+
import { useCallback, useContext, useEffect } from "react";
3+
import { clone, isEmpty, merge } from "lodash-es";
44
import { useHydrateAtoms } from "jotai/utils";
55
import {
66
appAtom,
@@ -30,6 +30,24 @@ interface ScreenContextProps {
3030

3131
type ScreenContextProviderProps = React.PropsWithChildren<ScreenContextProps>;
3232

33+
const transformScriptContent = (scriptContent: string): string => {
34+
if (isEmpty(scriptContent.trim())) {
35+
return "";
36+
}
37+
let transformed = scriptContent;
38+
// 1. Replace 'const VAR = ...' and 'let VAR = ...' with 'window.VAR = ...'
39+
transformed = transformed.replace(
40+
/(^|\n)(const|let)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=/g,
41+
"$1window.$3 =",
42+
);
43+
// 2. Replace 'function FUNC_NAME(...){...}' with 'window.FUNC_NAME = function(...){...}'
44+
transformed = transformed.replace(
45+
/(^|\n)function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(\([^)]*\))\s*\{/g,
46+
"$1window.$2 = function$3 {",
47+
);
48+
return transformed;
49+
};
50+
3351
export const ScreenContextProvider: React.FC<ScreenContextProviderProps> = ({
3452
screen,
3553
context,
@@ -42,6 +60,37 @@ export const ScreenContextProvider: React.FC<ScreenContextProviderProps> = ({
4260
throw new Error("Missing application context for screen!");
4361
}
4462

63+
useEffect(() => {
64+
const screenInstanceId = screen.name || screen.id || "anonymous-screen";
65+
const scriptId = `ensemble-screen-script-${screenInstanceId.replace(/[^a-zA-Z0-9]/g, "-")}`;
66+
let existingScript = document.getElementById(scriptId);
67+
68+
const globalScriptContent = screen.global || "";
69+
const importedScriptContent = screen.importedScripts || "";
70+
let fullScriptContent = `${importedScriptContent}\n\n${globalScriptContent}`;
71+
72+
fullScriptContent = transformScriptContent(fullScriptContent);
73+
74+
if (!isEmpty(fullScriptContent.trim())) {
75+
if (existingScript) {
76+
existingScript.remove();
77+
}
78+
79+
const scriptElement = document.createElement("script");
80+
scriptElement.id = scriptId;
81+
scriptElement.textContent = fullScriptContent;
82+
document.head.appendChild(scriptElement);
83+
84+
existingScript = scriptElement;
85+
}
86+
87+
return () => {
88+
if (existingScript) {
89+
existingScript.remove();
90+
}
91+
};
92+
}, [screen.global, screen.importedScripts, screen.name, screen.id]);
93+
4594
return (
4695
<Provider key={screen.name}>
4796
<HydrateAtoms

0 commit comments

Comments
 (0)