Open dvc94ch opened 6 years ago
Any thoughts on if this is:
a) possible b) in the scope of sprotty c) what would have to be done
There's always the possibility of using chromium-headless or something like that, but that a gigantic dependency I can't manage with yarn, so I'd rather not...
I think the only thing that strictly requires a browser is getBBox.
I think that is already possible using the snabbdom-to-html
package. See for example this test code:
You just need to create an instance of ModelRenderer through dependency injection like it's done in that test.
Got side tracked... The layout is not being applied to the svg correctly - 'updated model' is never logged as in the example, but the layout is performed. How do I get rid of Action is postponed due to block condition?
12:41:00 sprotty CommandStack: Executing SetModelCommand {
action: SetModelAction { newRoot: { type: 'NONE', id: 'EMPTY' }, kind: 'setModel' } }
layout
12:41:01 sprotty Viewer: rendering SModelRoot {
children: [],
canvasBounds: { x: 0, y: 0, width: -1, height: -1 },
type: 'NONE',
id: 'EMPTY' }
end layout
12:41:01 sprotty ActionDispatcher: Action is postponed due to block condition SetModelAction {
newRoot: { type: 'graph', id: 'netlist-graph', children: [ [Object] ] },
kind: 'setModel' }
import 'reflect-metadata';
import * as snabbdom from 'snabbdom-jsx';
import { Container } from 'inversify';
import { TYPES, SGraphFactory, ModelRendererFactory,
IVNodeDecorator, defaultModule, SModelRoot,
overrideViewerOptions, ConsoleLogger, LogLevel } from 'sprotty/lib';
import { NetlistGraphGenerator, configureSchematicModelElements,
ElkGraphLayout, ElkFactory, NetlistGraphModelSource, IGraphGenerator } from './browser';
import * as fs from 'fs'
import * as path from 'path'
import elkFactory from './browser/graph/elk-bundled';
const toHTML = require('snabbdom-to-html');
declare let global: any;
function createContainer(): Container {
const container = new Container();
container.load(defaultModule)
container.rebind(TYPES.IModelFactory).to(SGraphFactory).inSingletonScope();
container.rebind(TYPES.ILogger).to(ConsoleLogger).inSingletonScope();
container.rebind(TYPES.LogLevel).toConstantValue(LogLevel.log);
configureSchematicModelElements(container);
container.bind(IGraphGenerator).to(NetlistGraphGenerator).inSingletonScope()
container.bind(TYPES.ModelSource).to(NetlistGraphModelSource).inSingletonScope()
container.bind(TYPES.IModelLayoutEngine).to(ElkGraphLayout)
container.bind(ElkFactory).toConstantValue(elkFactory);
overrideViewerOptions(container, {
needsClientLayout: false,
needsServerLayout: true
});
return container
}
function getCss(paths: string[]): string {
let css = '';
for (let p of paths) {
css += fs.readFileSync(path.resolve(path.join(__dirname, p))).toString()
}
return css;
}
function renderGraph(graph: SModelRoot, style: string) {
const decorators = container.getAll<IVNodeDecorator>(TYPES.IVNodeDecorator);
const context = container.get<ModelRendererFactory>(TYPES.ModelRendererFactory)(decorators);
// For PreRenderedView to work
global.document = {createElement: snabbdom.svg, getElementById: () => null};
const vnode = context.renderElement(graph);
if (vnode.data && vnode.data.attrs && vnode.data.class) {
vnode.data.attrs['xmlns'] = 'http://www.w3.org/2000/svg'
vnode.data.class['sprotty'] = true
}
vnode.children = [].concat.apply([], [
[snabbdom.html('style', [], style)],
vnode.children || []
])
return toHTML(vnode)
}
const input = require('../tinyFPGA.lec.json')
const outputPath = path.resolve(__dirname + '/../tinyFPGA.svg')
const style = getCss([
'../src/cli.css',
'../src/browser/style/orientation.css',
'../src/browser/style/schematic.css',
])
const container = createContainer()
const modelSource = container.get<NetlistGraphModelSource>(TYPES.ModelSource);
modelSource.graphGenerator.addNetlist('netlist', input);
modelSource.updateModel().then(() => {
console.log('updated model')
const graphFactory = container.get<SGraphFactory>(TYPES.IModelFactory);
const graph = graphFactory.createRoot(modelSource.getModel())
console.log(graph)
fs.writeFileSync(outputPath, renderGraph(graph, style))
})
For some tasks - like generating reference documentation - it would be useful to have a headless mode that renders straight to svg.