neweb
Version:
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage percentage][coveralls-image]][coveralls-url] [ • 2.81 kB
text/typescript
import { JSDOM } from "jsdom";
import { Component, Document } from "neweb-components";
import { IPage } from "neweb-core";
import { BehaviorSubject, Observable, of } from "rxjs";
export interface IPageRendererConfig {
app: {
getFrameViewClass: (frameName: string) => any;
};
}
class PageRenderer {
constructor(protected config: IPageRendererConfig) { }
public async render(page: IPage) {
const views = await this.resolveViewClasses(page);
const dom = new JSDOM(`<!doctype><html><body><div id="root"></div></body></html>`, {
runScripts: "dangerously",
});
const window = dom.window;
const document = new Document({
window,
});
Component.setDocument(document);
const rootComponent = this.renderFrame(page.rootFrame, page, views);
rootComponent.mount();
const root = window.document.querySelector("#root") as HTMLElement;
root.appendChild(rootComponent.getRootElement());
const html = root.innerHTML;
// window.close();
return html;
}
protected renderFrame(
frameId: string, page: IPage,
views: { [index: string]: any },
): Component<any> {
const pageFrame = page.frames.filter((f) => f.frameId === frameId)[0];
const FrameView = views[pageFrame.frameId];
if (!FrameView) {
throw new Error("Not found frame " + pageFrame.frameName);
}
const children: { [index: string]: Component<any> } = {};
Object.keys(pageFrame.frames).map(async (placeName) => {
const childFrameId = pageFrame.frames[placeName];
// const childFrame = page.frames.filter((f) => f.frameId === childFrameId)[0];
children[placeName] = this.renderFrame(childFrameId, page, views);
});
const data: { [index: string]: Observable<any> } = {};
Object.keys(pageFrame.data).map((dataName) => {
data[dataName] = new BehaviorSubject(pageFrame.data[dataName]);
});
const component = new FrameView({
data,
children: new BehaviorSubject(children),
params: new BehaviorSubject(pageFrame.params),
seance: {
networkStatus: of("disconnected"),
navigateStatus: of("ready"),
},
});
return component;
}
protected async resolveViewClasses(page: IPage) {
const views: { [index: string]: any } = {};
await Promise.all(page.frames.map(async (pageFrame) => {
views[pageFrame.frameId] = await this.config.app.getFrameViewClass(pageFrame.frameName);
}));
return views;
}
}
export default PageRenderer;