Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Commit

Permalink
refactor(export): use message system for all exporters
Browse files Browse the repository at this point in the history
  • Loading branch information
Lasse Kuechler authored and marionebl committed May 24, 2018
1 parent fdb44c2 commit 7c33dcb
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 167 deletions.
10 changes: 10 additions & 0 deletions src/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const showSaveDialog = (options: Electron.SaveDialogOptions): Promise<string | u
new Promise(resolve => dialog.showSaveDialog(options, resolve));

const readFile = Util.promisify(Fs.readFile);
const writeFile = Util.promisify(Fs.writeFile);

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
Expand Down Expand Up @@ -83,6 +84,7 @@ async function createWindow(): Promise<void> {

// Handle messages that require
// access to system / fs
// tslint:disable-next-line:cyclomatic-complexity
switch (message.type) {
case ServerMessageType.AppLoaded: {
// Load last known file automatically in development
Expand Down Expand Up @@ -219,6 +221,14 @@ async function createWindow(): Promise<void> {
}

await Persistence.persist(project.getPath(), project);
break;
}
case ServerMessageType.ExportHTML:
case ServerMessageType.ExportPDF:
case ServerMessageType.ExportPNG:
case ServerMessageType.ExportSketch: {
const { path, content } = message.payload;
writeFile(path, content);
}
}
});
Expand Down
12 changes: 4 additions & 8 deletions src/electron/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ export function createMenu(): void {

if (path) {
const sketchExporter = new SketchExporter();
await sketchExporter.createExport();
await sketchExporter.writeToDisk(path);
sketchExporter.execute(path);
}
}
},
Expand All @@ -152,8 +151,7 @@ export function createMenu(): void {

if (path) {
const pdfExporter = new PdfExporter();
await pdfExporter.createExport();
await pdfExporter.writeToDisk(path);
pdfExporter.execute(path);
}
}
},
Expand All @@ -170,8 +168,7 @@ export function createMenu(): void {

if (path) {
const pngExporter = new PngExporter();
await pngExporter.createExport();
await pngExporter.writeToDisk(path);
pngExporter.execute(path);
}
}
},
Expand All @@ -191,8 +188,7 @@ export function createMenu(): void {

if (path) {
const htmlExporter = new HtmlExporter();
await htmlExporter.createExport();
await htmlExporter.writeToDisk(path);
htmlExporter.execute(path);
}
}
}
Expand Down
22 changes: 1 addition & 21 deletions src/export/exporter.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,9 @@
import { WebviewTag } from 'electron';
import * as Fs from 'fs';
import * as Util from 'util';

const writeFile = Util.promisify(Fs.writeFile);

export interface ExportResult {
error?: Error;
result?: Buffer;
}

export interface ExportWriteResult {
error?: Error;
}

export abstract class Exporter {
public contents: Buffer;

public abstract async createExport(webview: WebviewTag): Promise<ExportResult>;

public async writeToDisk(path: string): Promise<ExportWriteResult> {
try {
await writeFile(path, this.contents);
return {};
} catch (error) {
return { error };
}
}
public abstract execute(path: string): void;
}
24 changes: 15 additions & 9 deletions src/export/html-exporter.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import { createCompiler } from '../preview/create-compiler';
import { Exporter, ExportResult } from './exporter';
import * as Fs from 'fs';
import * as Path from 'path';
import { previewDocument, PreviewDocumentMode } from '../preview/preview-document';
import { ViewStore } from '../store';
import * as Util from 'util';
import * as uuid from 'uuid';

import * as Sender from '../message/client';
import { createCompiler } from '../preview/create-compiler';
import { Exporter } from './exporter';
import { ServerMessageType } from '../message';
import { previewDocument, PreviewDocumentMode } from '../preview/preview-document';
import { ViewStore } from '../store';

const SCRIPTS = ['vendor', 'renderer', 'components', 'preview'];

const createScript = (name: string, content: string) =>
`<script data-script="${name}">${content}<\/script>`;

export class HtmlExporter extends Exporter {
public async createExport(): Promise<ExportResult> {
public async execute(path: string): Promise<void> {
const store = ViewStore.getInstance();
const project = store.getCurrentProject();
const currentPage = store.getCurrentPage();
const styleguide = store.getStyleguide();

// TODO: Come up with good user-facing errors
if (!project || !currentPage || !styleguide) {
return {};
// Todo: Implement error message
return;
}

const data = {
Expand Down Expand Up @@ -54,8 +58,10 @@ export class HtmlExporter extends Exporter {

this.contents = Buffer.from(document);

return {
result: this.contents
};
Sender.send({
id: uuid.v4(),
type: ServerMessageType.ExportHTML,
payload: { path, content: this.contents }
});
}
}
176 changes: 89 additions & 87 deletions src/export/pdf-exporter.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,110 @@
import * as Url from 'url';
import * as uuid from 'uuid';

import * as Sender from '../message/client';
import { Exporter, ExportResult } from './exporter';
import { Exporter } from './exporter';
import { ServerMessageType } from '../message';
import { ViewStore } from '../store';
import * as Url from 'url';
import * as uuid from 'uuid';

export class PdfExporter extends Exporter {
public async createExport(): Promise<ExportResult> {
return new Promise<ExportResult>(resolve => {
const id = uuid.v4();
const initial = 'data:text/html;<html></html>';

const webview = document.createElement('webview');
webview.style.position = 'fixed';
webview.style.top = '100vh';
webview.src = initial;
webview.webpreferences = 'useContentSize=yes, javascript=no';
document.body.insertBefore(webview, document.body.firstChild);

const store = ViewStore.getInstance();
let started;

// (1) Request HTML contents from preview
const start = () => {
Sender.send({
payload: undefined,
type: ServerMessageType.ContentRequest,
id
});
};

// (2) Receive HTML response from preview and load into webview
// tslint:disable-next-line:no-any
const receive = message => {
if (message.type !== ServerMessageType.ContentResponse || message.id !== id) {
return;
}
public execute(path: string): void {
const id = uuid.v4();
const initial = 'data:text/html;<html></html>';

const webview = document.createElement('webview');
webview.style.position = 'fixed';
webview.style.top = '100vh';
webview.src = initial;
webview.webpreferences = 'useContentSize=yes, javascript=no';
document.body.insertBefore(webview, document.body.firstChild);

const store = ViewStore.getInstance();
let started;

// (1) Request HTML contents from preview
const start = () => {
Sender.send({
payload: undefined,
type: ServerMessageType.ContentRequest,
id
});
};

const payload = message.payload;
// (2) Receive HTML response from preview and load into webview
// tslint:disable-next-line:no-any
const receive = message => {
if (message.type !== ServerMessageType.ContentResponse || message.id !== id) {
return;
}

const parsed = Url.parse(payload.location);
const payload = message.payload;

if (parsed.host !== `localhost:${store.getServerPort()}`) {
return;
}
const parsed = Url.parse(payload.location);

webview.style.width = `${payload.width}px`;
webview.style.height = `${payload.height}px`;
if (parsed.host !== `localhost:${store.getServerPort()}`) {
return;
}

webview.loadURL(
`data:text/html;charset=utf-8,${encodeURIComponent(payload.document)}`,
{
baseURLForDataURL: payload.location
webview.style.width = `${payload.width}px`;
webview.style.height = `${payload.height}px`;

webview.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(payload.document)}`, {
baseURLForDataURL: payload.location
});
};

// (3) Wait for webview to be ready and capture the page
const createPdf = () => {
if (started !== id) {
return;
}

webview.printToPDF(
{
marginsType: 1,
pageSize: 'A4',
printBackground: true,
printSelectionOnly: false,
landscape: false
},
(error: Error, data: Buffer) => {
if (error) {
// Todo: Implement error message
// resolve({ error });
return;
}
);
};

// (3) Wait for webview to be ready and capture the page
const createPdf = () => {
if (started !== id) {
return;
}
this.contents = data;

webview.printToPDF(
{
marginsType: 1,
pageSize: 'A4',
printBackground: true,
printSelectionOnly: false,
landscape: false
},
(error: Error, data: Buffer) => {
if (error) {
resolve({ error });
return;
}

this.contents = data;
resolve({ result: this.contents });

setTimeout(() => {
document.body.removeChild(webview);
});
}
);
};
Sender.send({
id: uuid.v4(),
type: ServerMessageType.ExportPDF,
payload: { path, content: this.contents }
});

webview.addEventListener('did-finish-load', () => {
if (webview.src === initial) {
return;
setTimeout(() => {
document.body.removeChild(webview);
});
}
createPdf();
});
);
};

webview.addEventListener('did-finish-load', () => {
if (webview.src === initial) {
return;
}
createPdf();
});

Sender.receive(receive);
Sender.receive(receive);

webview.addEventListener('dom-ready', () => {
if (started === id) {
return;
}
webview.addEventListener('dom-ready', () => {
if (started === id) {
return;
}

started = id;
start();
});
started = id;
start();
});
}
}
33 changes: 20 additions & 13 deletions src/export/png-exporter.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import * as Sender from '../message/client';
import { remote } from 'electron';
import { Exporter, ExportResult } from './exporter';
import { ServerMessageType } from '../message';
import { ViewStore } from '../store';
import * as Url from 'url';
import * as uuid from 'uuid';

export class PngExporter extends Exporter {
public async createExport(): Promise<ExportResult> {
try {
this.contents = await this.createPngExport();
return { result: this.contents };
} catch (error) {
return { error };
}
}
import * as Sender from '../message/client';
import { Exporter } from './exporter';
import { ServerMessageType } from '../message';
import { ViewStore } from '../store';

export class PngExporter extends Exporter {
private async createPngExport(): Promise<Buffer> {
return new Promise<Buffer>(resolve => {
const id = uuid.v4();
Expand Down Expand Up @@ -119,4 +111,19 @@ export class PngExporter extends Exporter {
});
});
}

public async execute(path: string): Promise<void> {
try {
this.contents = await this.createPngExport();

Sender.send({
id: uuid.v4(),
type: ServerMessageType.ExportPNG,
payload: { path, content: this.contents }
});
} catch (error) {
// Todo: Implement error message
return;
}
}
}
Loading

0 comments on commit 7c33dcb

Please sign in to comment.