electron-secure-pos-printer
v1.1.4
Published
A secure POS (point of sale) printer for Electron
Downloads
38
Maintainers
Readme
electron-secure-pos-printer
A secure POS (point of sale) printer for Electron. By default, supports 58mm printers, however, it is very configurable, and is designed such that it can even be used without Electron (provided you supply the correct shims).
Note: The API for this module is inspired by electron-pos-printer, however it is NOT the same, so please pay close attention below if you are transitioning over from electron-pos-printer
.
Installation
NPM:
$ npm install electron-secure-pos-printer
Yarn:
$ yarn add electron-secure-pos-printer
Usage
The module requires only that you configure it in the main Electron process. No script imports or configuration are needed for the renderer HTML.
Step 1: Configure the IPC hooks for the main process
main.js
const Path = require('path');
const Electron = require('electron');
const { setupSecurePOSPrinter } = require('electron-secure-pos-printer');
var mainWindow;
function createWindow() {
mainWindow = new Electron.BrowserWindow({
width: 800,
height: 600,
show: true,
webPreferences: {
preload: Path.join(__dirname, 'preload.js')
},
});
// Load your app/site into the main window
mainWindow.loadFile(Path.join(__dirname, 'main.html'));
mainWindow.on('closed', function () {
mainWindow = null;
});
}
const app = Electron.app;
app.on('ready', () => {
// Setup secure bridge with renderer
setupSecurePOSPrinter(Electron);
createWindow();
});
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
if (mainWindow === null) {
createWindow();
}
});
Step 2: Preload for renderer process
preload.js
const { contextBridge, ipcRenderer } = require('electron');
const { setupSecureBridge } = require('electron-secure-pos-printer');
// Setup secure bridge with main process
setupSecureBridge(contextBridge, ipcRenderer);
Step 3: Inside your HTML
<!DOCTYPE html>
<html>
<head>
<title>Secure POS Printer Test</title>
<script>
// This global is exposed by Electron
/* global securePOSPrinter */
async function test() {
// Get a list of attached printers
var printers = await securePOSPrinter.getPrinters();
// Print some data
var data = [
{
type: 'text',
value: 'Testing 123',
},
{
type: 'qrCode',
value: 'https://www.saltlakefilmsociety.org/',
options: {
scale: 4,
},
},
{
type: 'barCode',
value: 123456789999,
},
{
// Path to image on file system
// mimeType is required when loading images from the file system
type: 'image',
path: './assets/printer-image.png',
mimeType: 'image/png',
}
{
// You can also specify a "src" attribute directly
type: 'image',
src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5gIREQQbbUH0CgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAMUlEQVQI13WOQQ4AIAzCWv//53kwmjiFYyGAAFBVbKmAjR7Ply6NK6Ufo7elqjye7k6T7hILeH2VsAAAAABJRU5ErkJggg==',
sectionStyle: {
alignItems: 'center',
justifyContent: 'center',
},
attributes: {
width: '100px',
height: '100px',
},
},
{
type: 'table',
header: [ 'Item', 'Price' ],
rows: [
[ 'Popcorn', '$5.00' ],
[ 'Soda', '$3.00' ],
[ 'Candy', '$2.00' ],
],
footer: [ 'Total', '$10.00' ],
},
];
var options = {
printerName: 'SomePrinterName',
// You can specify your own global stylesheet if you want
styleSheet: "body,#container { width: '110mm'}",
preview: true,
};
// Note: This promise will not resolve until
// 1) The preview window is shown, or
// 2) The document has been sent to the printer, or
// 3) An error occurred
await securePOSPrinter.print(data, options);
}
test();
</script>
</head>
<body>
</body>
</html>
Printing options
| Option | Description | Default Value |
| :------------- |:-------------| :----------: |
| addFinalMargin| (boolean) If true
, then add a little extra margin at the bottom of the print content | true
|
| bodyAttributes | (object) Attributes to assign directly to the body
tag in the document | null
|
| containerAttributes | (object) Attributes to assign directly to the <div id="container">
element in the document. Inside this container is where all the data
content is rendered | null
|
| copies | (number) number of copies to print | 1
|
| developmentMode | (boolean) If true
, then launch the dev-tools for the preview window (only works if preview
is true
) | false
|
| htmlAttributes | (object) Attributes to assign directly to the html
tag in the document | { lang: "en" }
|
| margin | (string) margin of a page, css values can be used | 0
|
| pageSize | (string) Specify the page medium for the printer | 'A4'
|
| preview | (boolean) preview in a window | false
|
| previewWindowHeight | (number) height of the preview window (in pixels) | 720
|
| previewWindowWidth | (number) width of the preview window (in pixels) | 360
|
| printerName | (string) the printer's name | null
|
| printOptions | (object) Options to pass directly to Electron.WebContents.print | null
|
| silent | (boolean) To print silently without printer selection pop-up | true
|
| styleSheet | (string/object) A style sheet (not a file name) to apply globally to the document. This gets inserted in the head
of the document. If this is an object, then the keys are selectors, and the values are StyleType | null
|
The Print data object (common)
| Option | Description | Default |
| :----------- | :-------------- | :---------: |
| sectionStyle | (StyleType) style to apply to this section (the container of this content) | null
|
| style | (StyleType) style to apply to this type | null
|
| type | (string) One of 'text'
, 'qrCode'
, 'barCode'
, 'image'
, 'table'
| 'text'
|
The Print data object (type = 'text')
| Option | Description | Default |
| :----------- | :-------------- | :---------: |
| raw | (boolean) If true
, then the value
provided will not be wrapped in a <span>
element | false
|
| value | (string) REQUIRED Content to put into this section | null
|
Note: By using raw: true
to can specify any HTML code you want as the value
Example:
var data = [
{
type: 'text',
value: 'Some content!',
// if `true`, then don't wrap content in a <span>
raw: false,
// Style applied to the <span> element,
// ignored if "raw = true"
style: { fontWeight: 'bold' },
sectionStyle: {
alignItems: 'center',
justifyContent: 'center',
},
}
];
The Print data object (type = 'qrCode')
| Option | Description | Default |
| :----------- | :-------------- | :---------: |
| attributes | (object) Attributes to assign to the <img>
tag | null
|
| height | (number) Height in pixels for the generated QR code image | null
|
| options | (object) Options object to pass directly to qrcode.options | null
|
| value | (string) REQUIRED Content to encode into the QR code | null
|
| width | (number) Width in pixels for the generated QR code image | null
|
Note: The QR code is generated with qrcode
as a PNG image encoded in a data:
URI.
Example:
var data = [
{
type: 'qrCode',
value: 'Some content!',
// Style applied to the <img> element
style: { width: '40mm', height: '40mm' },
sectionStyle: {
alignItems: 'center',
justifyContent: 'center',
},
options: {
scale: 10,
}
}
];
The Print data object (type = 'barCode')
| Option | Description | Default |
| :----------- | :-------------- | :---------: |
| attributes | (object) Attributes to assign to the <img>
tag | null
|
| height | (number) Height in pixels for the generated bar code image | null
|
| options | (object) Options object to pass directly to jsbarcode.options | null
|
| value | (number) REQUIRED ID to encode into the bar code | null
|
| width | (number) Width in pixels for the generated bar code image | null
|
Note: The barcode is generated with jsbarcode
as an SVG image encoded in a data:
URI.
Example:
var data = [
{
type: 'barCode',
value: 123456789999,
// Style applied to the <img> element
style: { width: '40mm' },
sectionStyle: {
alignItems: 'center',
justifyContent: 'center',
},
options: {
format: 'CODE128',
}
}
];
The Print data object (type = 'image')
| Option | Description | Default |
| :----------- | :-------------- | :---------: |
| attributes | (object) Attributes to assign to the <img>
tag | null
|
| height | (number) Height in pixels for the image | null
|
| path | (string) Path on file system to image. If you specify this option then you must also specify a mimeType
for the image | null
|
| mimeType | (string) This is required if you specify a path
| null
|
| src | (string) Specify the src
attribute of the image directly. If path
is specified, that will take precedence over this option | null
|
| width | (number) Width in pixels for the image | null
|
Note 1: One of path
+ mimeType
, or src
are required
Note 2: If path
is specified, the image will be loaded from disk, and encoded as a data:
URI, using the mimeType
you specified
Example:
var data = [
{
type: 'image',
path: './assets/some-image.png',
mimeType: 'image/png',
// Style applied to the <img> element
style: { width: '40mm', height: '40mm' },
sectionStyle: {
alignItems: 'center',
justifyContent: 'center',
},
},
{
type: 'image',
src: 'https://image-cdn.com/some-image.png',
// Style applied to the <img> element
style: { width: '40mm', height: '40mm' },
sectionStyle: {
alignItems: 'center',
justifyContent: 'center',
},
}
];
The Print data object (type = 'table')
| Option | Description | Default |
| :----------- | :-------------- | :---------: |
| bodyAttributes | (object) Attributes to assign to the <tbody>
tag | null
|
| bodyStyle | (StyleType) Style to apply to the <tbody>
tag | null
|
| columnAttributes | (object) Attributes to assign to all <td>
tags | null
|
| columnStyle | (StyleType) Style to apply to all <td>
tags | null
|
| footer | (array[string]) Columns for the footer. If not specified, then there will be no table footer | null
|
| footerAttributes | (object) Attributes to assign to the <tfoot>
tag | null
|
| footerStyle | (StyleType) Style to apply to the <tfoot>
tag | null
|
| header | (array[string]) Columns for the header. If not specified, then there will be no table header | null
|
| headerAttributes | (object) Attributes to assign to the <thead>
tag | null
|
| headerStyle | (StyleType) Style to apply to the <thead>
tag | null
|
| rowAttributes | (object) Attributes to assign to all <tr>
or <th>
tags | null
|
| rows | (array[array[string]]) REQUIRED An array (rows) of arrays (columns) for the table | null
|
| rowStyle | (StyleType) Style to apply to all <tr>
or <th>
tags | null
|
| tableAttributes | (object) Attributes to assign to the <table>
tag | null
|
| tableStyle | (StyleType) Style to apply to the <table>
tag | null
|
Note: The number of columns must be the same for every row or an exception will be thrown
Example:
var data = [
{
type: 'table',
header: [ 'Item', 'Price' ],
rows: [
[ 'Popcorn', '$5.00' ],
[ 'Soda', '$3.00' ],
[ 'Candy', '$2.00' ],
],
footer: [ 'Total', '$10.00' ],
},
];
StyleType
Styles can be applied to elements in a number of different ways. All of the following style definitions can validly be given to any style option:
- As a string:
'border-width: 0.5mm; color: red;'
- As an object:
{ borderWidth: '0.5mm', color: 'red' }
- As an array of strings or objects:
[ 'border-width: 0.5mm; color: red;', { borderWidth: '0.5mm', color: 'red' }, rootStyleObject ]
. If using an array of styles, then all styles will be parsed and merged into a single style sheet.
Note: When using object notation for styles, if you use a number
for any value, then by default it will be converted into a mm
unit. For example, { width: 10 }
would be converted into 'width: 10mm'
automatically. If a certain style actually needs a raw number, then specify your style as a string instead.
About the HTML content for the printer
The content that gets renderered for the printer has roughly the following structure:
<html>
<head>
<!-- Default and custom style sheets get injected here -->
</head>
<!-- The "preview" class is applied to the body if in preview mode -->
<body class="preview">
<div id="container">
<div class="section">
<!-- content from "data" goes here -->
</div>
<div class="section">
<!-- content from "data" goes here -->
</div>
...
</div>
</body>
</html>
Refer to ./src/main-style-sheet.css
for the default styles applied to the print document.
If you request preview: true
in the options, then extra scripts and content will be injected into the preview document to enable the "Cancel" and "Print" buttons at the top of the preview to function properly.
Sponors
Many thanks to all our sponors!
This work was sponsored by MAST @ Salt Lake Film Society