Skip to content

Commit 95cb952

Browse files
committed
add import src base url + vdom fallback
1 parent 12e7d20 commit 95cb952

File tree

8 files changed

+213
-75
lines changed

8 files changed

+213
-75
lines changed

idom/client/app/index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424

2525
let endpoint = protocol + "//" + url.join("/") + window.location.search;
2626

27-
mountLayoutWithWebSocket(document.getElementById("app"), endpoint);
27+
mountLayoutWithWebSocket(
28+
document.getElementById("app"),
29+
endpoint,
30+
"../web_modules/"
31+
);
2832
</script>
2933
</body>
3034
</html>

idom/client/app/package-lock.json

Lines changed: 36 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

idom/client/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"test": "echo \"Error: no test specified\" && exit 1"
1919
},
2020
"devDependencies": {
21-
"prettier": "2.1.1",
21+
"prettier": "^2.2.1",
2222
"snowpack": "2.12.1"
2323
},
2424
"dependencies": {

idom/client/app/src/layout.js

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ import * as jsonpatch from "fast-json-patch";
66
import serializeEvent from "./event-to-object";
77

88
const html = htm.bind(react.createElement);
9-
const alreadyImported = {};
9+
const LayoutConfigContext = react.createContext({});
1010

11-
export function mountLayoutWithWebSocket(mountElement, endpoint) {
11+
export function mountLayoutWithWebSocket(
12+
mountElement,
13+
endpoint,
14+
importSourceUrl
15+
) {
1216
if (endpoint.startsWith(".") || endpoint.startsWith("/")) {
1317
let loc = window.location;
1418
let protocol;
@@ -42,70 +46,116 @@ export function mountLayoutWithWebSocket(mountElement, endpoint) {
4246
);
4347
}
4448

45-
return mountLayout(mountElement, saveUpdateHook, sendCallback);
49+
return mountLayout(
50+
mountElement,
51+
saveUpdateHook,
52+
sendCallback,
53+
importSourceUrl
54+
);
4655
}
4756

48-
export function mountLayout(mountElement, saveUpdateHook, sendEvent) {
57+
export function mountLayout(
58+
mountElement,
59+
saveUpdateHook,
60+
sendEvent,
61+
importSourceUrl
62+
) {
4963
reactDOM.render(
50-
html`<${Layout} saveUpdateHook=${saveUpdateHook} sendEvent=${sendEvent} />`,
64+
html`
65+
<${Layout}
66+
saveUpdateHook=${saveUpdateHook}
67+
sendEvent=${sendEvent}
68+
importSourceUrl=${importSourceUrl}
69+
/>
70+
`,
5171
mountElement
5272
);
5373
}
5474

55-
export default function Layout({ saveUpdateHook, sendEvent }) {
75+
export default function Layout({ saveUpdateHook, sendEvent, importSourceUrl }) {
5676
const [model, patchModel] = useInplaceJsonPatch({});
5777

5878
react.useEffect(() => saveUpdateHook(patchModel), [patchModel]);
5979

6080
if (model.tagName) {
61-
return html`<${Element} sendEvent=${sendEvent} model=${model} />`;
81+
return html`
82+
<${LayoutConfigContext.Provider}
83+
value=${{
84+
sendEvent: sendEvent,
85+
importSourceUrl: importSourceUrl,
86+
}}
87+
>
88+
<${Element} model=${model} />
89+
<//>
90+
`;
6291
} else {
6392
return html`<div />`;
6493
}
6594
}
6695

67-
function Element({ sendEvent, model }) {
96+
function Element({ model }) {
6897
if (model.importSource) {
69-
return html`<${LazyElement} sendEvent=${sendEvent} model=${model} />`;
98+
return html`<${ImportedElement} model=${model} />`;
7099
} else {
71-
const children = elementChildren(sendEvent, model);
72-
const attributes = elementAttributes(sendEvent, model);
73-
if (model.children && model.children.length) {
74-
return html`<${model.tagName} ...${attributes}>${children}<//>`;
75-
} else {
76-
return html`<${model.tagName} ...${attributes} />`;
77-
}
100+
return html`<${StandardElement} model=${model} />`;
78101
}
79102
}
80103

81-
function LazyElement({ sendEvent, model }) {
82-
const module = useLazyModule(model.importSource.source);
104+
function ImportedElement({ model }) {
105+
const config = react.useContext(LayoutConfigContext);
106+
const module = useLazyModule(
107+
model.importSource.source,
108+
config.importSourceUrl
109+
);
83110
if (module) {
84111
const cmpt = getPathProperty(module, model.tagName);
85-
const children = elementChildren(sendEvent, model);
86-
const attributes = elementAttributes(sendEvent, model);
112+
const children = elementChildren(model);
113+
const attributes = elementAttributes(model, config.sendEvent);
87114
return html`<${cmpt} ...${attributes}>${children}<//>`;
88115
} else {
89-
return html`<div>${model.importSource.fallback}<//>`;
116+
return createElement(model.importSource.fallback);
117+
}
118+
}
119+
120+
function StandardElement({ model }) {
121+
const config = react.useContext(LayoutConfigContext);
122+
const children = elementChildren(model);
123+
const attributes = elementAttributes(model, config.sendEvent);
124+
if (model.children && model.children.length) {
125+
return html`<${model.tagName} ...${attributes}>${children}<//>`;
126+
} else {
127+
return html`<${model.tagName} ...${attributes} />`;
128+
}
129+
}
130+
131+
function createElement(value) {
132+
if (!value) {
133+
return html`<div />`;
134+
}
135+
switch (typeof value) {
136+
case "object":
137+
return html`<${Element} model=${value} />`;
138+
case "string":
139+
return html`<div>${value}</div>`;
90140
}
91141
}
92142

93-
function elementChildren(sendEvent, model) {
143+
function elementChildren(model) {
94144
if (!model.children) {
95145
return [];
96146
} else {
97147
return model.children.map((child) => {
98148
switch (typeof child) {
99149
case "object":
100-
return html`<${Element} model=${child} sendEvent=${sendEvent} />`;
150+
return html`<${Element} model=${child} />`;
101151
case "string":
102152
return child;
103153
}
104154
});
105155
}
106156
}
107157

108-
function elementAttributes(sendEvent, model) {
158+
function elementAttributes(model, sendEvent) {
109159
const attributes = Object.assign({}, model.attributes);
110160

111161
if (model.eventHandlers) {
@@ -144,10 +194,12 @@ function eventHandler(sendEvent, eventSpec) {
144194
};
145195
}
146196

147-
function useLazyModule(source) {
148-
const [module, setModule] = react.useState(alreadyImported[source]);
197+
function useLazyModule(source, sourceUrl = "") {
198+
const [module, setModule] = react.useState(null);
149199
if (!module) {
150-
dynamicImport(source).then(setModule);
200+
dynamicImport(
201+
source.startsWith("./") ? sourceUrl + source.slice(2) : source
202+
).then(setModule);
151203
}
152204
return module;
153205
}
@@ -161,7 +213,7 @@ function dynamicImport(source) {
161213
} else {
162214
console.log(error);
163215
return {
164-
default: function Catch() {
216+
default() {
165217
return html`
166218
<pre>
167219
<h1>Error</h1>

idom/client/manage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def web_module_exports(package_name: str) -> List[str]:
2626

2727
def web_module_url(package_name: str) -> str:
2828
web_module_path(package_name, must_exist=True)
29-
return f"../web_modules/{package_name}.js"
29+
return f"./{package_name}.js"
3030

3131

3232
def web_module_exists(package_name: str) -> bool:

0 commit comments

Comments
 (0)