Skip to content

Commit 7ffe5ca

Browse files
committed
Enhance code.LivePreview to support nested windows #8074
1 parent 531ddd9 commit 7ffe5ca

6 files changed

Lines changed: 75 additions & 51 deletions

File tree

src/code/LivePreview.mjs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ class LivePreview extends Container {
107107
value_: null,
108108
/**
109109
* The url for the child app to use for the popout window
110-
* @member {String} windowUrl='./childapps/preview/index.html'
110+
* @member {String} windowUrl_='./childapps/preview/index.html'
111111
* @reactive
112112
*/
113-
windowUrl: './childapps/preview/index.html'
113+
windowUrl_: './childapps/preview/index.html'
114114
}
115115

116116
/**
@@ -199,6 +199,24 @@ class LivePreview extends Container {
199199
return this.beforeSetEnumValue(value, oldValue, 'language')
200200
}
201201

202+
/**
203+
* Triggered before the language config gets changed
204+
* @param {String} value
205+
* @param {String} oldValue
206+
* @returns {String}
207+
* @protected
208+
*/
209+
beforeSetWindowUrl(value, oldValue) {
210+
if (value.startsWith('./')) {
211+
let appPath = Neo.config.appPath.split('/');
212+
appPath.pop()
213+
214+
return new URL(Neo.config.basePath + appPath.join('/') + value.substring(1), location.href).href
215+
}
216+
217+
return value
218+
}
219+
202220
/**
203221
* @param {Object} data
204222
*/
@@ -327,25 +345,18 @@ class LivePreview extends Container {
327345

328346
container.removeAll();
329347
container.add({
330-
module: me.markdownComponentClass,
331-
style : {height: '100%', overflow: 'auto'},
332-
value : source
348+
module : me.markdownComponentClass,
349+
style : {height: '100%', overflow: 'auto'},
350+
value : source,
351+
windowUrl: me.windowUrl
333352
})
334353
} else {
335354
if (!me.neoExecutor) {
336355
const module = await import('./executor/Neo.mjs');
337356
me.neoExecutor = Neo.create(module.default);
338357
}
339358

340-
await me.neoExecutor.execute({
341-
code: source,
342-
container: container,
343-
context: {
344-
appName : me.appName,
345-
windowId : me.windowId,
346-
parentComponent: me
347-
}
348-
})
359+
await me.neoExecutor.execute({code: source, container})
349360
}
350361
}
351362

src/code/executor/Neo.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class NeoExecutor extends Base {
8181
* instead of using a cached version.
8282
* @param {Object} data
8383
* @param {String} data.code
84-
* @param {Neo.component.Base} data.container
84+
* @param {Neo.container.Base} data.container
8585
* @returns {Promise<Object>}
8686
*/
8787
async execute({code, container}) {

src/component/Markdown.mjs

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ class Markdown extends Component {
4545
* @member {String|null} value_=null
4646
* @reactive
4747
*/
48-
value_: null
48+
value_: null,
49+
/**
50+
* Optional windowUrl to pass to nested code.LivePreviews.
51+
* @member {String|null} windowUrl=null
52+
*/
53+
windowUrl: null
4954
}
5055

5156
/**
@@ -86,20 +91,24 @@ class Markdown extends Component {
8691
// Clean up previous instances
8792
me.destroyComponents();
8893

89-
await me.render({
90-
code : value,
91-
container: me,
92-
context: {
93-
appName : me.appName,
94-
windowId : me.windowId,
95-
parentComponent: me
96-
}
97-
});
94+
await me.render({code: value})
9895
}
9996
}
10097

98+
/**
99+
* Triggered after the windowId config got changed
100+
* @param {String|null} value
101+
* @param {String|null} oldValue
102+
* @protected
103+
*/
104+
async afterSetWindowId(value, oldValue) {
105+
super.afterSetWindowId(value, oldValue);
106+
this.activeComponents.forEach(component => component.windowId = value)
107+
}
108+
101109
/**
102110
* Destroy all created child instances
111+
* @param {...*} args
103112
*/
104113
destroy(...args) {
105114
this.destroyComponents();
@@ -113,7 +122,7 @@ class Markdown extends Component {
113122
let me = this;
114123

115124
me.activeComponents.forEach(component => component.destroy());
116-
me.activeComponents = [];
125+
me.activeComponents = []
117126
}
118127

119128
/**
@@ -247,22 +256,19 @@ class Markdown extends Component {
247256
* the actual Neo.mjs components, rendering them into the placeholder DIVs within the generated HTML.
248257
* @param {Object} data
249258
* @param {String} data.code
250-
* @param {Neo.component.Base} data.container
251-
* @param {Object} [data.context]
252259
* @returns {Promise<Object>}
253260
*/
254-
async render({code, container, context={}}) {
255-
let me = this,
256-
content = code,
257-
neoComponents = {},
258-
neoDivs = {},
259-
parentComponent = context.parentComponent || container,
260-
baseConfigs = {
261-
appName : context.appName,
262-
autoInitVnode: true,
263-
autoMount : true,
264-
parentComponent,
265-
windowId : context.windowId || parentComponent.windowId
261+
async render({code}) {
262+
let me = this,
263+
content = code,
264+
neoComponents = {},
265+
neoDivs = {},
266+
baseConfigs = {
267+
appName : me.appName,
268+
autoInitVnode : true,
269+
autoMount : true,
270+
parentComponent: me.parentComponent,
271+
windowId : me.windowId
266272
},
267273
html, instance;
268274

@@ -285,9 +291,7 @@ class Markdown extends Component {
285291
html = marked.parse(content);
286292

287293
// Insert lab divs (these are markdown comments, so process on the final HTML)
288-
html = me.insertLabDivs(html);
289-
290-
container.html = html;
294+
me.html = me.insertLabDivs(html);
291295

292296
await new Promise(resolve => setTimeout(resolve, Neo.config.environment === 'development' ? 100 : 150));
293297

@@ -299,9 +303,7 @@ class Markdown extends Component {
299303
parentId : key,
300304
...neoComponents[key]
301305
});
302-
me.activeComponents.push(instance);
303-
304-
console.log(me.activeComponents);
306+
me.activeComponents.push(instance)
305307
});
306308
}
307309

@@ -310,12 +312,18 @@ class Markdown extends Component {
310312
const LivePreviewClass = LivePreviewModule.default;
311313

312314
Object.keys(neoDivs).forEach(key => {
313-
instance = Neo.create({
315+
const config = {
314316
...baseConfigs,
315317
module : LivePreviewClass,
316318
parentId: key,
317319
value : neoDivs[key].code
318-
});
320+
}
321+
322+
if (me.windowUrl) {
323+
config.windowUrl = me.windowUrl
324+
}
325+
326+
instance = Neo.create(config);
319327
me.activeComponents.push(instance);
320328
});
321329
}
@@ -329,7 +337,7 @@ class Markdown extends Component {
329337
*/
330338
updateComponentState(mounted) {
331339
this.activeComponents.forEach(component => {
332-
if (mounted) {console.log('remount cmp', component.id);
340+
if (mounted) {
333341
component.initVnode(true)
334342
} else {
335343
component.mounted = false

src/component/wrapper/MonacoEditor.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class MonacoEditor extends Base {
388388
scrollBeyondLastLine: me.scrollBeyondLastLine,
389389
theme : me.editorTheme,
390390
value : me.stringifyValue(me.value),
391+
windowId : me.windowId,
391392

392393
scrollbar: {
393394
alwaysConsumeMouseWheel: false // enables page scrolling when over-scrolling the content box

src/container/Base.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ class Container extends Component {
351351
parent.remove?.(item, false);
352352
delete item.vdom.removeDom;
353353

354+
if (parent.windowId !== me.windowId) {
355+
item.mounted = false
356+
}
357+
354358
// Convenience logic, especially for moving components into different browser windows:
355359
// A component might rely on references & handler methods inside the previous controller realm
356360
// todo: We need ?. until functional.component.Base supports controllers

src/main/addon/MonacoEditor.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class MonacoEditor extends Base {
9797
* @returns {Object}
9898
*/
9999
getValue(data) {
100-
return this.map[data.id].getModel().getValue()
100+
return this.map[data.id]?.getModel().getValue()
101101
}
102102

103103
/**
@@ -106,7 +106,7 @@ class MonacoEditor extends Base {
106106
* @param {String} data.id
107107
*/
108108
layoutEditor(data) {
109-
this.map[data.id].layout()
109+
this.map[data.id]?.layout()
110110
}
111111

112112
/**

0 commit comments

Comments
 (0)