@levischuck/receiptline
v0.1.5
Published
Markdown for receipts. Printable digital receipts. Generate receipt printer commands and images.
Maintainers
Readme
ReceiptLine
Markdown for receipts. Printable digital receipts. 茶 Generate receipt printer commands, SVG images, and HTML documents.
ReceiptLine is the receipt description language that expresses the output image of small roll paper. It supports printing paper receipts using a receipt printer and displaying electronic receipts on a POS system or smartphone. It can be described simply with receipt markdown text data that does not depend on the paper width.
Installation
$ npm install @levischuck/receiptlineUsage
receiptline.transform() method transforms ReceiptLine document to printer commands, SVG images, or HTML documents.
import { transform, SvgTarget, HtmlTarget } from "@levischuck/receiptline";
const body = `Example Receipt
{image:iVBORw0KGgoAAAANSUhEUgAAAHAAAAAYCAMAAAAVmYlOAAAAAXNSR0IB2cksfwAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZQTFRFAAAA////pdmf3QAAAAlwSFlzAAAuIwAALiMBeKU/dgAAALZJREFUSMftlVESgCAIROH+l25qLIUFRMfpw9EvU5ZnuBTxz4MOcAsglRFEyU0lCKUR0Nc5wLI6A3zTpIGtYBbIo0BeA1TFfeYpoL4VyBIC69I9HQC+kZilRDklFblooKTG2pckMo0IGjGNFOLxrLaoDz7QbAsUymgyG1/sxkB84TSQ3cuL2sK8I7ek6NIuMOQvASqX5oE+kfAIbeeRfuqYllj1HtrC0bceypUUPkraOOePvwvwAi2zCEzzMOsBAAAAAElFTkSuQmCC}
(Merchant Copy)
---
{w: * 4 8}
{b:line}
|Product | Qty| Price
--
|Pad Thai | 1| 14.99
|Spring Roll | 1| 4.99
--
{w:* 8}
| Subtotal| 19.98
| Tax (6%)| 1.20
| Convenience Fee| 0.99
| Total| 22.17
---
{b:space}
{w:auto}
Please Sign:
---
{c:https://levischuck.com;o:qrcode,6}
Please Take our Survey`;
// SVG Target
const svgTarget = new SvgTarget();
svgTarget.setDefaultFont("'Atkinson Hyperlegible Mono'");
const {content: svg, width, height} = await transform(body, {
cpl: charactersPerLine,
charWidth: charWidth,
target: svgTarget,
});
// HTML Target
const htmlTarget = new HtmlTarget();
htmlTarget.setDefaultFont("'Google Sans Code', monospace");
htmlTarget.setActualFontCharacterWidth(13.2); // Actual measured width of your font
htmlTarget.setCharHeight(24); // Character height in pixels
const {content: html, width: htmlWidth, height: htmlHeight} = await transform(body, {
cpl: charactersPerLine,
charWidth: charWidth,
target: htmlTarget,
});
c
// Do something interesting with the SVG or HTML afterwardsMethod
transform(doc[, options])
Parameters
doc- a string of ReceiptLine document
options- an object of printer configuration
Return value
content: SVG Image (for SvgTarget) or HTML string (for HtmlTarget)width: Width of the generated content in pixelsheight: Height of the generated content in pixels
Printer configuration
cpl- characters per line (default:
48)
- characters per line (default:
charWidth- dot width of each character (default:
12).
- dot width of each character (default:
spacingfalse: no line spacing (default)true: line spacing
margin(for printer)- print margin (left) (range:
0-24, default:0)
- print margin (left) (range:
marginRight(for printer)- print margin (right) (range:
0-24, default:0)
- print margin (right) (range:
targetWhat implementation to use (SvgTarget for SVG output, HtmlTarget for HTML output, instantiate your own to set additional configuration like font)encodingcp437(default), others exist if you need to look. They mostly adjust line spacing and default fonts.
cpl * charWidth will be the output width, which by default is 576 dots.
HTML Target Configuration
The HTML target provides additional configuration options to account for differences with web fonts and the defaults this library expects for a thermal printer.
setDefaultFont(font: string)- Sets the CSS font-family for the receipt (default: "'Courier Prime', monospace")setActualFontCharacterWidth(width: number | undefined)- Sets the actual measured character width of your font in pixels. It'll keep the text from going off the side when correctly set.setCharHeight(height: number | undefined)- Explicitly sets the character height in pixels. If not set, defaults tocharWidth * 2(usually 12 * 2)
When using the HTML target, you may need to measure your font's actual character width for optimal layout. This is especially important when using web fonts that don't fit the 12 dot wide, 24 dot tall convention.
const htmlTarget = new HtmlTarget();
htmlTarget.setDefaultFont("'Google Sans Code', monospace");
htmlTarget.setActualFontCharacterWidth(13.2);
htmlTarget.setCharHeight(24.7);Examples
example/data/*
The documents (receipt markdown text) are the same as the examples in the OFSC ReceiptLine Specification.
Grammar
Structure
The receipt is made of a table, which separates each column with a pipe |.
|Line|Content|Description| |---|---|---| |column| column || columncolumn ||TextProperty|Single column| |column | column | column | column || column | columncolumn | column ||Text|Double column| |column | ... | column| column | ... | column || column | ... | columncolumn | ... | column ||Text|Multiple columns|
Alignment
The column is attracted to the pipe | like a magnet.
␣ means one or more whitespaces.
|Column|Description| |---|---| |column|column||␣column␣||Center| ||column|column␣|column␣||Left| |column||␣column||␣column|Right|
Text
The text is valid for any column.
Asparagus | 0.99
Broccoli | 1.99
Carrot | 2.99
---
^TOTAL | ^5.97Characters are printed in a monospace font (12 x 24 px). Wide characters are twice as wide as Latin characters (24 x 24 px). Control characters are ignored.
Special characters in text
Special characters are assigned to characters that are rarely used in the receipt.
|Special character|Description|
|---|---|
|\|Character escape|
|||Column delimiter|
|{|Property delimiter (Start)|
|}|Property delimiter (End)|
|- (1 or more, exclusive)|Horizontal rule|
|= (1 or more, exclusive)|Paper cut|
|~|Space|
|_|Underline|
|"|Emphasis|
|`|Invert|
|^|Double width|
|^^|Double height|
|^^^|2x size|
|^^^^|3x size|
|^^^^^|4x size|
|^^^^^^|5x size|
|^^^^^^^ (7 or more)|6x size|
Escape sequences in text
Escape special characters.
|Escape sequence|Description|
|---|---|
|\\|\|
|\||||
|\{|{|
|\}|}|
|\-|- (Cancel horizontal rule)|
|\=|= (Cancel paper cut)|
|\~|~|
|\_|_|
|\"|_|
|\` |`|
|\^|^|
|\n|Wrap text manually|
|\xnn|Hexadecimal character code|
|\char (Others)|Ignore|
Properties
The property is valid for lines with a single column.
{ width: * 10; comment: the column width is specified in characters }|Key|Abbreviation|Value|Case-sensitive|Default|Saved|Description|
|---|---|---|---|---|---|---|
|image|i|base64 png format|✓|-|-|Image(Recommended: monochrome, critical chunks only)|
|code|c|textdata|✓|-|-|Barcode / 2D code|
|option|o|see below|-|code128 2 72 nohri 3 l|✓|Barcode / 2D code options(Options are separated by commas or one or more whitespaces)|
|align|a|leftcenterright|-|center|✓|Line alignment(Valid when line width < CPL)|
|width|w|auto*0 -|-|auto(* for all columns)|✓|Column widths (chars)(Widths are separated by commas or one or more whitespaces)|
|border|b|linespacenone0 - 2|-|space|✓|Column border (chars)(Border width: line=1, space=1, none=0)|
|text|t|wrapnowrap|-|wrap|✓|Text wrapping|
|command|x|textdata|✓|-|-|Device-specific commands|
|comment|_|textdata|✓|-|-|Comment|
Barcode options
Barcode options are separated by commas or one or more whitespaces.
|Barcode option|Description|
|---|---|
|upc|UPC-A, UPC-E(Check digit can be omitted)|
|eanjan|EAN-13, EAN-8(Check digit can be omitted)|
|code39|CODE39|
|itf|Interleaved 2 of 5|
|codabarnw7|Codabar (NW-7)|
|code93|CODE93|
|code128|CODE128|
|2 - 4|Barcode module width (px)|
|24 - 240|Barcode module height (px)|
|hri|With human readable interpretation|
|nohri|Without human readable interpretation|
2D code options
2D code options are separated by commas or one or more whitespaces.
|2D code option|Description|
|---|---|
|qrcode|QR Code|
|3 - 8|Cell size (px)|
|lmqh|Error correction level|
Special characters in property values
Special characters in property values are different from special characters in text.
|Special character|Description|
|---|---|
|\|Character escape|
|||Column delimiter|
|{|Property delimiter (Start)|
|}|Property delimiter (End)|
|:|Key-value separator|
|;|Key-value delimiter|
Escape sequences in property values
Escape special characters.
|Escape sequence|Description|
|---|---|
|\\|\|
|\||||
|\{|{|
|\}|}|
|\;|;|
|\n|New line|
|\xnn|Hexadecimal character code|
|\char (Others)|Ignore|
Why use this one over the reference implementation?
The original library has a weird hack to generate UUIDs on insecure contexts to get around a currently debated WebCrypto standards detail. This prevented me from deploying to Cloudflare workers. This fork and typescript adjustment is enough to unblock my objective.
I also wanted to use a diferent font.
License
Apache 2 Licensed, per the original source
The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED http://www.denso-wave.com/qrcode/faqpatent-e.html
Author
Open Foodservice System Consortium http://www.ofsc.or.jp/
Levi Schuck https://levischuck.com/
