@Component({
selector: 'eg-root',
- template: '<router-outlet></router-outlet><eg-print></eg-print>'
+ template: '<router-outlet></router-outlet>'
})
export class BaseComponent {
// consider moving these to core...
import {HatchService} from '@eg/share/print/hatch.service';
+import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service';
import {PrintService} from '@eg/share/print/print.service';
// Globally available components
return {
ngModule: EgCommonModule,
providers: [
+ HtmlToTxtService,
HatchService,
PrintService,
ToastService
import {HatchService, HatchMessage} from '@eg/core/hatch.service';
import {ToastService} from '@eg/share/toast/toast.service';
import {StringService} from '@eg/share/string/string.service';
+import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service';
+const HATCH_FILE_WRITER_PRINTER = 'hatch_file_writer';
@Component({
selector: 'eg-print',
private elm: ElementRef,
private store: StoreService,
private serverStore: ServerStoreService,
+ private h2txt: HtmlToTxtService,
private hatch: HatchService,
private toast: ToastService,
private strings: StringService,
}
printViaHatch(printReq: PrintRequest) {
+ if (!printReq.contentType) {
+ printReq.contentType = 'text/html';
+ }
// Send a full HTML document to Hatch
let html = printReq.text;
this.serverStore.getItem(`eg.print.config.${printReq.printContext}`)
.then(config => {
- const msg = new HatchMessage({
- action: 'print',
- content: html,
- settings: config || {},
- contentType: 'text/html',
- showDialog: printReq.showDialog
- });
+ let msg: HatchMessage;
+
+ if (config && config.printer === HATCH_FILE_WRITER_PRINTER) {
+
+ const text = printReq.contentType === 'text/plain' ?
+ html : this.h2txt.htmlToTxt(html);
+
+ msg = new HatchMessage({
+ action: 'set',
+ key: `receipt.${printReq.printContext}.txt`,
+ content: text,
+ bare: true
+ });
+
+ } else {
+
+ msg = new HatchMessage({
+ action: 'print',
+ content: html,
+ settings: config || {},
+ contentType: 'text/html',
+ showDialog: printReq.showDialog
+ });
+ }
this.hatch.sendRequest(msg).then(
ok => console.debug('Print request succeeded'),
--- /dev/null
+import {Injectable} from '@angular/core';
+
+const ENTITY_REGEX = /&[^\s]+;/;
+
+/**
+ * Translates HTML text into plain text.
+ */
+
+@Injectable()
+export class HtmlToTxtService {
+
+ unEscapeHtml(text: string): string {
+ text = text.replace(/&/g, '&');
+ text = text.replace(/"/g, '"');
+ text = text.replace(/ /g, ' ');
+ text = text.replace(/</g, '<');
+ text = text.replace(/>/g, '>');
+ return text;
+ }
+
+ // https://stackoverflow.com/questions/7394748
+ entityToChars(text: string): string {
+ if (text && text.match(ENTITY_REGEX)) {
+ const node = document.createElement('textarea');
+ node.innerHTML = text;
+ return node.value;
+ }
+ return text;
+ }
+
+ // Translate an HTML string into plain text.
+ // Removes HTML elements.
+ // Replaces <li> with "*"
+ // Replaces HTML entities with their character equivalent.
+ htmlToTxt(html: string): string {
+ if (!html || html === '') {
+ return '';
+ }
+
+ // First remove multi-line comments.
+ html = html.replace(/<!--(.*?)-->/gs, '');
+
+ const lines = html.split(/\n/);
+ const newLines = [];
+
+ lines.forEach(line => {
+
+ if (!line) {
+ newLines.push(line);
+ return;
+ }
+
+ line = this.unEscapeHtml(line);
+ line = this.entityToChars(line);
+
+ line = line.replace(/<head.*?>.*?<\/head>/gi, '');
+ line = line.replace(/<br.*?>/gi, '\r\n');
+ line = line.replace(/<table.*?>/gi, '');
+ line = line.replace(/<\/tr>/gi, '\r\n'); // end of row
+ line = line.replace(/<\/td>/gi, ' '); // end of cell
+ line = line.replace(/<\/th>/gi, ' '); // end of th
+ line = line.replace(/<tr.*?>/gi, '');
+ line = line.replace(/<hr.*?>/gi, '\r\n');
+ line = line.replace(/<p.*?>/gi, '');
+ line = line.replace(/<block.*?>/gi, '');
+ line = line.replace(/<li.*?>/gi, ' * ');
+ line = line.replace(/<.+?>/gi, '');
+
+ if (line) { newLines.push(line); }
+ });
+
+ return newLines.join('\n');
+ }
+}
+
import {GridComponent} from '@eg/share/grid/grid.component';
import * as Moment from 'moment-timezone';
import {SampleDataService} from '@eg/share/util/sample-data.service';
+import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service';
@Component({
templateUrl: 'sandbox.component.html',
private toast: ToastService,
private format: FormatService,
private printer: PrintService,
- private samples: SampleDataService
+ private samples: SampleDataService,
+ private h2txt: HtmlToTxtService
) {
// BroadcastChannel is not yet defined in PhantomJS and elsewhere
this.sbChannel = (typeof BroadcastChannel === 'undefined') ?
}
} )
});
+
+ const str = 'César & Me';
+ console.log(this.h2txt.htmlToTxt(str));
}
sbChannelHandler = msg => {
<!-- global toast alerts -->
<eg-toast></eg-toast>
+
+<!-- global print handler component -->
+<eg-print></eg-print>
+