npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

electron-secure-pos-printer

v1.1.4

Published

A secure POS (point of sale) printer for Electron

Downloads

38

Readme

License Version Issues

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:

  1. As a string: 'border-width: 0.5mm; color: red;'
  2. As an object: { borderWidth: '0.5mm', color: 'red' }
  3. 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

MAST