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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@piqy/epos-ast

v0.1.0

Published

TypeScript types and utilities for representing ESC/POS commands as a unist syntax tree

Readme

ESC/POS Abstract Syntax Tree


epos-ast is a specification for representing ESC/POS commands in a syntax tree. It implements unist. ESC/POS is a command system developed by Epson for controlling point-of-sale receipt printers. Since 1980s, numerous manufacturers have reverse-engineered and adopted the specification.

This specification is written in a Web IDL-like grammar.

This package provides a pure TypeScript implementation of the specification.

epos-ast can be used to:

  • Parse binary ESC/POS data into a structured, inspectable format
  • Transform receipt data (modify, filter, translate)
  • Convert to other formats (HTML, Markdown, PDF)
  • Generate ESC/POS binary data from structured input
  • Analyze receipt content programmatically

Contents

Nodes (abstract)

Literal

interface Literal <: UnistLiteral {
  value: string
}

Literal ([UnistLiteral][dfn-unist-literal]) represents an abstract interface in epos-ast containing a value.

Its value field is a string.

Parent

interface Parent <: UnistParent {
  children: [FlowContent]
}

Parent ([UnistParent][dfn-unist-parent]) represents an abstract interface in epos-ast containing other nodes (said to be [children][term-child]).

Its content is limited to only other epos-ast content.

Nodes

Root

interface Root <: Parent {
  type: 'root'
  children: [FlowContent]
}

Root (Parent) represents a complete print job or receipt.

Root can be used as the [root][term-root] of a tree, never as a [child][term-child]. Its content model is flow content.

A Root represents one TCP connection or one serial transmission (delimited by full cuts).

For example, a simple receipt:

{
  type: 'root',
  children: [
    {
      type: 'align',
      align: 'center',
      children: [
        { type: 'text', value: 'RECEIPT' },
        { type: 'break' }
      ]
    },
    { type: 'cut', mode: 'full' }
  ]
}

Text

interface Text <: Literal {
  type: 'text'
  codepage: number?
  country: Country?
}

Text (Literal) represents printable text content.

Text can be used where phrasing content is expected. Its content is represented by its value field.

A codepage field can be present. It specifies the ESC/POS codepage number for encoding during serialization. When not present, defaults to 19 (CP858). See Codepage reference for supported values.

A country field can be present. It specifies country-specific character variations for serialization.

The stringifier emits ESC t and ESC R commands when the codepage or country changes between text nodes.

For example:

{ type: 'text', value: 'Hello, World!' }
{ type: 'text', value: 'café', codepage: 19, country: 'france' }

Break

interface Break <: Node {
  type: 'break'
}

Break ([Node][dfn-unist-node]) represents a line feed (LF).

Break can be used where phrasing content is expected. It has no content model.

Yields: 0A

Tab

interface Tab <: Node {
  type: 'tab'
}

Tab ([Node][dfn-unist-node]) represents a horizontal tab (HT).

Tab can be used where phrasing content is expected. It has no content model.

Tab positions are defined by TabStops.

Yields: 09

Strong

interface Strong <: Parent {
  type: 'strong'
  children: [PhrasingContent]
}

Strong (Parent) represents bold/emphasized text using ESC E.

Strong can be used where phrasing content is expected. Its content model is phrasing content.

Yields: 1B 45 01 + children + 1B 45 00

Underline

interface Underline <: Parent {
  type: 'underline'
  double?: boolean
  children: [PhrasingContent]
}

Underline (Parent) represents underlined text using ESC -.

Underline can be used where phrasing content is expected. Its content model is phrasing content.

A double field can be present. When true, uses double (2-dot) underline. When not present or false, uses single (1-dot) underline.

Yields: 1B 2D n + children + 1B 2D 00 where n = 2 if double, 1 otherwise

Inverted

interface Inverted <: Parent {
  type: 'inverted'
  children: [PhrasingContent]
}

Inverted (Parent) represents reverse-printed text (white text on black background) using GS B.

Inverted can be used where phrasing content is expected. Its content model is phrasing content.

Yields: 1D 42 01 + children + 1D 42 00

Scaled

interface Scaled <: Parent {
  type: 'scaled'
  width: 1 <= number <= 8
  height: 1 <= number <= 8
  children: [PhrasingContent]
}

Scaled (Parent) represents enlarged text with width and/or height multipliers using GS !.

Scaled can be used where phrasing content is expected. Its content model is phrasing content.

A width field must be present. It represents the horizontal size multiplier (1-8).

A height field must be present. It represents the vertical size multiplier (1-8).

Yields: 1D 21 n + children + 1D 21 00 where n = ((width-1) << 4) | (height-1)

Rotated

interface Rotated <: Parent {
  type: 'rotated'
  spacing: RotationSpacing?
  children: [PhrasingContent]
}

Rotated (Parent) represents 90° clockwise rotated text using ESC V.

Rotated can be used where phrasing content is expected. Its content model is phrasing content.

A spacing field may be present. It represents character spacing during rotation mode. Defaults to 1 (1-dot spacing).

Yields: 1B 56 n + children + 1B 56 00 where n = 1 for 1-dot spacing, n = 2 for 1.5-dot spacing

UpsideDown

interface UpsideDown <: Parent {
  type: 'upsideDown'
  children: [PhrasingContent]
}

UpsideDown (Parent) represents 180°-rotated text printed right-to-left using ESC {.

UpsideDown can be used where phrasing content is expected. Its content model is phrasing content.

Note: Only effective in Standard mode at the beginning of a line. Does not affect graphics or raster images.

Yields: 1B 7B 01 + children + 1B 7B 00

Smoothing

interface Smoothing <: Parent {
  type: 'smoothing'
  children: [PhrasingContent]
}

Smoothing (Parent) represents smoothed character rendering using GS b.

Smoothing can be used where phrasing content is expected. Its content model is phrasing content.

Note: Only effective for quadruple-size (4x) or larger characters.

Yields: 1D 62 01 + children + 1D 62 00

DoubleStrike

interface DoubleStrike <: Parent {
  type: 'doubleStrike'
  children: [PhrasingContent]
}

DoubleStrike (Parent) represents double-strike printed text (prints each line twice for darker output) using ESC G.

DoubleStrike can be used where phrasing content is expected. Its content model is phrasing content.

Yields: 1B 47 01 + children + 1B 47 00

Font

interface Font <: Parent {
  type: 'font'
  font: FontType
  children: [PhrasingContent]
}

Font (Parent) represents a font selection using ESC M.

Font can be used where phrasing content is expected. Its content model is phrasing content.

A font field must be present. Font A is typically 12x24 dots, Font B is 9x17 dots. Availability of other fonts varies by printer model.

Settings are effective until ESC !, ESC @, reset, or power off.

Yields: 1B 4D n + children where n = 0 (A), 1 (B), 2 (C), 3 (D), 4 (E), 97 (specialA), 98 (specialB). Stringifier restores previous font after children.

Align

interface Align <: Parent {
  type: 'align'
  align: AlignType
  children: [FlowContent]
}

Align (Parent) represents text alignment using ESC a.

Align can be used where flow content is expected. Its content model is also flow content.

An align field must be present. It represents horizontal text alignment.

Yields: 1B 61 n + children where n = 0 (left), 1 (center), 2 (right). Stringifier restores previous alignment after children.

LineSpacing

interface LineSpacing <: Parent {
  type: 'lineSpacing'
  spacing: number | 'default'
  children: [FlowContent]
}

LineSpacing (Parent) represents line spacing configuration using ESC 3 or ESC 2.

LineSpacing can be used where flow content is expected. Its content model is also flow content.

A spacing field must be present. When a number, it represents spacing in canonical units. When 'default', it resets to the printer's default line spacing.

Yields: 1B 33 n + children where n = spacing, or 1B 32 for default. Stringifier restores previous spacing after children.

CharacterSpacing

interface CharacterSpacing <: Parent {
  type: 'characterSpacing'
  spacing: number
  children: [FlowContent]
}

CharacterSpacing (Parent) represents right-side character spacing using ESC SP.

CharacterSpacing can be used where flow content is expected. Its content model is also flow content.

A spacing field must be present. It represents additional spacing added to the right side of each character, in canonical units.

Yields: 1B 20 n + children where n = spacing. Stringifier restores previous spacing after children.

Position

interface Position <: Node {
  type: 'position'
  horizontal: number
  mode: PositionMode
}

Position ([Node][dfn-unist-node]) represents absolute or relative horizontal print position movement using ESC $ (absolute) or [ESC ](https://download4.epson.biz/sec_pubs/pos/reference_en/escpos/esc_backslash.html) (relative).

Position can be used where phrasing content is expected. It has no content model.

A horizontal field must be present. It represents horizontal position in canonical units.

A mode field must be present. It represents whether positioning is absolute (from origin) or relative (from current position).

Yields: 1B 24 nL nH (absolute) or 1B 5C nL nH (relative) where nL/nH = position as low/high byte

Feed

interface Feed <: Node {
  type: 'feed'
  lines: number?
  units: number?
  reverse: boolean?
}

Feed ([Node][dfn-unist-node]) represents paper feed commands using ESC d (lines), ESC J (units), or ESC e (reverse).

Feed can be used where flow content is expected. It has no content model.

Either a lines or units field should be present, but not both.

A lines field represents the number of lines to feed.

A units field represents feed distance in canonical units.

A reverse field can be present. When true, paper feeds in reverse direction. Not all printers support reverse feed.

Yields: 1B 64 n (lines), 1B 4A n (units), or 1B 65 n (reverse lines)

Cut

interface Cut <: Node {
  type: 'cut'
  mode: CutType
  feed: number?
}

Cut ([Node][dfn-unist-node]) represents paper cutting commands using GS V, ESC i, or ESC m.

Cut can be used where flow content is expected. It has no content model.

A mode field must be present. It represents the type of cut to perform.

A feed field can be present. It represents lines to feed before cutting.

Yields: 1D 56 00 (full), 1B 69 (partial-1), 1B 6D (partial-3), or 1D 56 42 n (full with feed)

Pulse

interface Pulse <: Node {
  type: 'pulse'
  pin: DrawerPin
  onTime: number
  offTime: number
}

Pulse ([Node][dfn-unist-node]) represents a pulse output signal using ESC p.

Pulse can be used where flow content is expected. It has no content model.

Typically used to drive cash drawers, but can also control external buzzers or other devices connected to the drawer kick-out connector.

A pin field must be present. It represents which connector pin to pulse ('pin2' for connector pin 2, 'pin5' for connector pin 5).

An onTime field must be present. It represents pulse ON time in units of 2ms.

An offTime field must be present. It represents pulse OFF time in units of 2ms.

Yields: 1B 70 m t1 t2 where m = 0 (pin2) or 1 (pin5), t1 = onTime, t2 = offTime

Image

interface Image <: Node {
  type: 'image'
  width: number
  height: number
  data: string
}

Image ([Node][dfn-unist-node]) represents a printed image using GS ( L / GS 8 L Function 112 (store) and Function 50 (print).

Image can be used where flow content is expected. It has no content model.

A width field must be present. It represents image width in pixels.

A height field must be present. It represents image height in pixels.

A data field must be present. It contains base64-encoded bitmap data in normalized raster format: row-major, 1 bit per pixel, MSB is leftmost pixel. Each row is padded to byte boundary.

The parser normalizes all image formats (GS v 0, ESC *, GS ( L) into this representation. The stringifier always outputs using GS ( L Function 112 + Function 50.

Note: ESC/POS supports grayscale (multiple tone) and multi-color (up to 4 colors for 2-color thermal paper) images via the a and c parameters of Function 112. This AST currently only supports monochrome images, which covers the vast majority of receipt printing use cases. Grayscale/color support may be added in a future version if needed.

Yields: 1D 28 4C pL pH 30 70 30 01 01 31 xL xH yL yH d... (Function 112) + 1D 28 4C 02 00 30 32 (Function 50)

Barcode

interface Barcode <: Node {
  type: 'barcode'
  format: BarcodeFormat
  data: string
  width: number?
  height: number?
  hri: HriPosition?
  hriFont: HriFont?
}

Barcode ([Node][dfn-unist-node]) represents a 1D barcode using GS k, with optional configuration via GS w (width), GS h (height), GS H (HRI position), and GS f (HRI font).

Barcode can be used where flow content is expected. It has no content model.

A format field must be present. It represents the barcode symbology.

A data field must be present. It contains the data to encode. Valid characters depend on the barcode format.

A width field can be present. It represents the module (bar) width in dots (1-6).

A height field can be present. It represents the barcode height in dots.

An hri field can be present. It represents where to print Human Readable Interpretation text.

An hriFont field can be present. It represents which font to use for HRI text.

Yields: 1D 77 n (width) + 1D 68 n (height) + 1D 48 n (HRI) + 1D 66 n (font) + 1D 6B m d... where m = format, d = data

QRCode

interface QRCode <: Node {
  type: 'qrCode'
  data: string
  model: QRModel?
  size: number?
  errorCorrection: ErrorCorrection?
}

QRCode ([Node][dfn-unist-node]) represents a QR code using GS ( k (cn=49) with functions 165 (model), 167 (size), 169 (error correction), 180 (store), and 181 (print).

QRCode can be used where flow content is expected. It has no content model.

A data field must be present. It contains the data to encode.

A model field can be present. Model 1 is the original QR code; Model 2 is an enhanced version with higher capacity. When not present, defaults to 2.

A size field can be present. It represents module size (1-16). When not present, defaults to 3.

An errorCorrection field can be present. When not present, defaults to 'L'.

Yields: 1D 28 6B 04 00 31 41 n 00 (model) + 1D 28 6B 03 00 31 43 n (size) + 1D 28 6B 03 00 31 45 n (error) + 1D 28 6B pL pH 31 50 30 d... (store) + 1D 28 6B 03 00 31 51 30 (print)

PDF417

interface PDF417 <: Node {
  type: 'pdf417'
  data: string
  columns: number?
  rows: number?
  width: number?
  height: number?
  errorCorrection: PDF417ErrorCorrection?
  truncated: boolean?
}

PDF417 ([Node][dfn-unist-node]) represents a PDF417 2D barcode using GS ( k (cn=48) with functions 065 (columns), 066 (rows), 067 (width), 068 (height), 069 (error), 070 (options), 080 (store), and 081 (print).

PDF417 can be used where flow content is expected. It has no content model.

A data field must be present. It contains the data to encode.

A columns field can be present. It represents the number of data columns (0-30). 0 = auto.

A rows field can be present. It represents the number of rows (0, 3-90). 0 = auto.

A width field can be present. It represents module width (2-8).

A height field can be present. It represents row height (2-8).

An errorCorrection field can be present. It specifies error correction using a PDF417ErrorCorrection union:

  • { mode: 'level', level: 0-8 }: Specific error correction level (fn069 m=48, n=level+48)
  • { mode: 'ratio', ratio: 1-400 }: Error correction as ratio percentage (fn069 m=49, n=ratio)

A truncated field can be present. When true, generates truncated PDF417.

Yields: 1D 28 6B 03 00 30 41 n (columns) + 1D 28 6B 03 00 30 42 n (rows) + 1D 28 6B 03 00 30 43 n (width) + 1D 28 6B 03 00 30 44 n (height) + 1D 28 6B 04 00 30 45 m n (error) + 1D 28 6B 03 00 30 46 n (options) + 1D 28 6B pL pH 30 50 30 d... (store) + 1D 28 6B 03 00 30 51 30 (print)

DataMatrix

interface DataMatrix <: Node {
  type: 'dataMatrix'
  data: string
  symbolType: DataMatrixType?
  columns: number?
  rows: number?
  size: number?
}

DataMatrix ([Node][dfn-unist-node]) represents a DataMatrix 2D barcode using GS ( k (cn=54) with functions 666 (type/columns/rows), 667 (module size), 680 (store), and 681 (print).

DataMatrix can be used where flow content is expected. It has no content model.

A data field must be present. It contains the data to encode.

A symbolType field can be present. It represents the symbol type (square or rectangular). When not present, defaults to 'square'.

A columns field can be present. It represents the number of columns. When not present, auto-selected based on data length.

A rows field can be present. It represents the number of rows. When not present, auto-selected based on data length.

A size field can be present. It represents module size (2-16).

Yields: 1D 28 6B 05 00 36 42 d1 d2 d3 (type/columns/rows) + 1D 28 6B 03 00 36 43 n (module size) + 1D 28 6B pL pH 36 50 30 d... (store) + 1D 28 6B 03 00 36 51 30 (print)

MaxiCode

interface MaxiCode <: Node {
  type: 'maxiCode'
  data: string
  mode: MaxiCodeMode?
}

MaxiCode ([Node][dfn-unist-node]) represents a MaxiCode 2D barcode using GS ( k (cn=50) with functions 265 (mode), 280 (store), and 281 (print).

MaxiCode can be used where flow content is expected. It has no content model.

A data field must be present. It contains the data to encode.

A mode field can be present. Mode 2 is for structured carrier message (US), Mode 3 for non-US, Mode 4 for standard symbol, Mode 5 for full ECC, Mode 6 for reader programming. When not present, defaults to 4.

Yields: 1D 28 6B 03 00 32 41 n (mode) + 1D 28 6B pL pH 32 50 30 d... (store) + 1D 28 6B 03 00 32 51 30 (print)

AztecCode

interface AztecCode <: Node {
  type: 'aztecCode'
  data: string
  mode: AztecMode?
  layers: number?
  size: number?
  errorCorrection: number?
}

AztecCode ([Node][dfn-unist-node]) represents an Aztec Code 2D barcode using GS ( k (cn=53) with functions 566 (mode/layers), 567 (size), 569 (error correction), 580 (store), and 581 (print).

AztecCode can be used where flow content is expected. It has no content model.

A data field must be present. It contains the data to encode.

A mode field can be present. 'full' is the full-range symbol, 'compact' is the compact symbol. When not present, defaults to 'full'.

A layers field can be present. It represents the number of data layers (1-32 for full, 1-4 for compact). When not present, auto-selected.

A size field can be present. It represents module size (2-16).

An errorCorrection field can be present. It represents error correction percentage (5-95). When not present, defaults to 23.

Yields: 1D 28 6B 04 00 35 42 m n (mode/layers) + 1D 28 6B 03 00 35 43 n (size) + 1D 28 6B 04 00 35 45 n1 n2 (error) + 1D 28 6B pL pH 35 50 30 d... (store) + 1D 28 6B 03 00 35 51 30 (print)

GS1DataBar

interface GS1DataBar <: Node {
  type: 'gs1DataBar'
  symbology: GS1DataBarSymbology
  data: string
  width: number?
  maxWidth: number?
}

GS1DataBar ([Node][dfn-unist-node]) represents a GS1 DataBar (formerly RSS) 2D barcode using GS ( k (cn=51) with functions 367 (width), 371 (max width for Expanded Stacked), 380 (store), and 381 (print).

GS1DataBar can be used where flow content is expected. It has no content model.

A symbology field must be present. It represents the GS1 DataBar variant (GS1DataBarSymbology), encoded as the n parameter in fn380.

A data field must be present. It contains the symbol data to encode (without the symbology identifier byte).

A width field can be present. It represents module width (2-8).

A maxWidth field can be present. It represents maximum width for Expanded Stacked variants.

Yields: 1D 28 6B 03 00 33 43 n (width) + 1D 28 6B 04 00 33 47 nL nH (max width) + 1D 28 6B pL pH 33 50 30 n d... (store) + 1D 28 6B 03 00 33 51 30 (print)

Composite

interface Composite <: Node {
  type: 'composite'
  lineElement: CompositeLineElement
  element2D: Composite2DElement
  width: number?
  maxWidth: number?
  hriFont: HriFont | null?
}

interface CompositeLineElement {
  barcode: CompositeLineBarcode
  symbology: CompositeGS1DataBarVariant?
  data: string
}

interface Composite2DElement {
  symbology: Composite2DSymbology
  data: string
}

Composite ([Node][dfn-unist-node]) represents a Composite Symbology barcode (combining linear and 2D components) using GS ( k (cn=52) with functions 467 (width), 471 (max width), 472 (HRI font), 480 (store), and 481 (print).

Composite can be used where flow content is expected. It has no content model.

A lineElement field must be present. It describes the linear (1D) barcode component, stored via fn480 with a=48. The barcode sub-field identifies the barcode type (CompositeLineBarcode). When barcode is 'GS1-DATABAR', the optional symbology sub-field specifies the GS1 DataBar variant (CompositeGS1DataBarVariant). The data sub-field contains the encoded data.

An element2D field must be present. It describes the 2D composite component, stored via fn480 with a=49. The symbology sub-field identifies the 2D symbology type (Composite2DSymbology). The data sub-field contains the encoded data.

A width field can be present. It represents module width (2-8).

A maxWidth field can be present. It represents maximum width for Expanded Stacked variants.

An hriFont field can be present. It represents the font for HRI text. When null, HRI text is not added (fn472 n=0).

Yields: 1D 28 6B 03 00 34 43 n (width) + 1D 28 6B 04 00 34 47 nL nH (max width) + 1D 28 6B 03 00 34 48 n (HRI font) + 1D 28 6B pL pH 34 50 30 b d... (store line element, a=48) + 1D 28 6B pL pH 34 50 31 b d... (store 2D element, a=49) + 1D 28 6B 03 00 34 51 30 (print)

TabStops

interface TabStops <: Parent {
  type: 'tabStops'
  stops: [number]
  children: [FlowContent]
}

TabStops (Parent) represents horizontal tab position configuration using ESC D.

TabStops can be used where flow content is expected. Its content model is also flow content.

A stops field must be present. It is a list of column positions where tabs stop. Maximum 32 positions.

Yields: 1B 44 n1 n2 ... nk 00 + children where n1...nk = stop positions. Stringifier restores previous tab stops after children.

Color

interface Color <: Parent {
  type: 'color'
  color: PrintColor
  children: [PhrasingContent]
}

Color (Parent) represents print color selection using ESC r.

Color can be used where phrasing content is expected. Its content model is phrasing content.

A color field must be present.

Note: Two-color printing requires compatible printer and paper.

Yields: 1B 72 n + children where n = 0 (black), 1 (red). Stringifier restores previous color after children.

Margin

interface Margin <: Parent {
  type: 'margin'
  left: number
  children: [FlowContent]
}

Margin (Parent) represents left margin configuration using GS L.

Margin can be used where flow content is expected. Its content model is also flow content.

A left field must be present. It represents the left margin in canonical units.

Yields: 1D 4C nL nH + children where nL/nH = left margin as low/high byte. Stringifier restores previous margin after children.

PrintArea

interface PrintArea <: Parent {
  type: 'printArea'
  width: number
  children: [FlowContent]
}

PrintArea (Parent) represents print area width configuration using GS W.

PrintArea can be used where flow content is expected. Its content model is also flow content.

A width field must be present. It represents the print area width in canonical units.

Yields: 1D 57 nL nH + children where nL/nH = width as low/high byte. Stringifier restores previous width after children.

Raw

interface Raw <: Literal {
  type: 'raw'
  value: string
  description: string?
}

Raw (Literal) represents unrecognized or vendor-specific command bytes.

Raw can be used where flow or phrasing content is expected. It has no content model.

A value field must be present. It contains base64-encoded raw bytes.

A description field can be present. It provides a human-readable description of the unknown command.

This node ensures lossless parsing of ESC/POS data even when commands are not recognized.

Yields: decoded bytes from value field (unchanged)

Enumeration

AlignType

enum AlignType {
  'left' | 'center' | 'right'
}

AlignType represents horizontal text alignment.

  • 'left': Left-aligned (default)
  • 'center': Centered
  • 'right': Right-aligned

CutType

enum CutType {
  'full' | 'partial-1' | 'partial-3'
}

CutType represents paper cut mode.

  • 'full': Full cut (complete paper separation)
  • 'partial-1': Partial cut with 1 point left uncut (ESC i)
  • 'partial-3': Partial cut with 3 points left uncut (ESC m)

Country

enum Country {
  'usa' | 'france' | 'germany' | 'uk' | 'denmark-1' | 'sweden' |
  'italy' | 'spain-1' | 'japan' | 'norway' | 'denmark-2' | 'spain-2' |
  'latin-america' | 'korea' | 'slovenia' | 'china' | 'vietnam' | 'arabia' |
  'india-devanagari' | 'india-bengali' | 'india-tamil' | 'india-telugu' |
  'india-assamese' | 'india-oriya' | 'india-kannada' | 'india-malayalam' |
  'india-gujarati' | 'india-punjabi' | 'india-marathi'
}

Country represents international character set selection. Each country defines variations for specific ASCII positions:

| Code | Country | 23 | 24 | 25 | 2A | 40 | 5B | 5C | 5D | 5E | 60 | 7B | 7C | 7D | 7E | | ---- | ------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | 0 | usa | # | $ | % | * | @ | [ | \ | ] | ^ | | { | \| | } | ~ | | 1 | france | # | $ | % | \* | à | ° | ç | § | ^ | | é | ù | è | ¨ | | 2 | germany | # | $ | % | * | § | Ä | Ö | Ü | ^ | | ä | ö | ü | ß | | 3 | uk | £ | $ | % | \* | @ | [ | \ | ] | ^ | | { | | | } | ~ | | 4 | denmark-1 | # | $ | % | * | @ | Æ | Ø | Å | ^ | | æ | ø | å | ~ | | 5 | sweden | # | ¤ | % | \* | É | Ä | Ö | Å | Ü | é | ä | ö | å | ü | | 6 | italy | # | $ | % | \* | @ | ° | \ | é | ^ | ù | à | ò | è | ì | | 7 | spain-1 | ₧ | $ | % | \* | @ | ¡ | Ñ | ¿ | ^ | | ¨ | ñ | } | ~ | | 8 | japan | # | $ | % | * | @ | [ | ¥ | ] | ^ | | { | \| | } | ~ | | 9 | norway | # | ¤ | % | \* | É | Æ | Ø | Å | Ü | é | æ | ø | å | ü | | 10 | denmark-2 | # | $ | % | \* | É | Æ | Ø | Å | Ü | é | æ | ø | å | ü | | 11 | spain-2 | # | $ | % | \* | á | ¡ | Ñ | ¿ | é | | í | ñ | ó | ú | | 12 | latin-america | # | $ | % | * | á | ¡ | Ñ | ¿ | é | ü | í | ñ | ó | ú | | 13 | korea | # | $ | % | * | @ | [ | ₩ | ] | ^ | | { | \| | } | ~ | | 14 | slovenia | # | $ | % | \* | Ž | Š | Đ | Ć | Č | ž | š | đ | ć | č | | 15 | china | # | ¥ | % | \* | @ | [ | \ | ] | ^ | | { | | | } | ~ | | 16 | vietnam | đ | $ | % | * | @ | [ | \ | ] | ^ | | { | \| | } | ~ | | 17 | arabia | # | $ | ٪ | \* | @ | [ | \ | ] | ^ | | { | | | } | ~ |

India character sets (codes 66-75, 82) replace ASCII positions 30-39 with language-specific numerals.

BarcodeFormat

enum BarcodeFormat {
  'UPC-A' | 'UPC-E' | 'EAN13' | 'EAN8' |
  'CODE39' | 'ITF' | 'CODABAR' | 'CODE93' | 'CODE128'
}

BarcodeFormat represents 1D barcode symbology.

HriPosition

enum HriPosition {
  'none' | 'above' | 'below' | 'both'
}

HriPosition represents Human Readable Interpretation text position.

  • 'none': No HRI text
  • 'above': HRI printed above barcode
  • 'below': HRI printed below barcode
  • 'both': HRI printed above and below

ErrorCorrection

enum ErrorCorrection {
  'L' | 'M' | 'Q' | 'H'
}

ErrorCorrection represents QR code error correction level.

  • 'L': Low (~7% recovery)
  • 'M': Medium (~15% recovery)
  • 'Q': Quartile (~25% recovery)
  • 'H': High (~30% recovery)

PositionMode

enum PositionMode {
  'absolute' | 'relative'
}

PositionMode represents print position movement type.

  • 'absolute': Position from origin
  • 'relative': Position from current location

FontType

enum FontType {
  'A' | 'B' | 'C' | 'D' | 'E' | 'specialA' | 'specialB'
}

FontType represents the printer font selection.

  • 'A': Font A (typically 12x24 dots)
  • 'B': Font B (typically 9x17 dots)
  • 'C', 'D', 'E': Additional fonts (availability varies by printer)
  • 'specialA', 'specialB': Special fonts

PrintColor

enum PrintColor {
  'black' | 'red'
}

PrintColor represents print color selection.

  • 'black': Black ink (default)
  • 'red': Red ink (requires compatible printer and paper)

RotationSpacing

enum RotationSpacing {
  1 | 1.5
}

RotationSpacing represents character spacing for 90° clockwise rotation mode.

  • 1: 1-dot character spacing (ESC V n=1/49)
  • 1.5: 1.5-dot character spacing (ESC V n=2/50)

QRModel

enum QRModel {
  1 | 2
}

QRModel represents QR code model selection.

  • 1: Model 1 (original)
  • 2: Model 2 (enhanced capacity)

MaxiCodeMode

enum MaxiCodeMode {
  2 | 3 | 4 | 5 | 6
}

MaxiCodeMode represents MaxiCode symbol mode.

  • 2: Structured carrier message (US)
  • 3: Structured carrier message (non-US)
  • 4: Standard symbol, SEC
  • 5: Full ECC symbol
  • 6: Reader programming

AztecMode

enum AztecMode {
  'full' | 'compact'
}

AztecMode represents Aztec Code symbol type.

  • 'full': Full-range symbol (1-32 layers)
  • 'compact': Compact symbol (1-4 layers)

DataMatrixType

enum DataMatrixType {
  'square' | 'rectangular'
}

DataMatrixType represents DataMatrix symbol shape.

  • 'square': Square symbol (default)
  • 'rectangular': Rectangular symbol

GS1DataBarSymbology

enum GS1DataBarSymbology {
  'STACKED' | 'STACKED-OMNIDIRECTIONAL' | 'EXPANDED-STACKED'
}

GS1DataBarSymbology represents the GS1 DataBar variant (fn380 n parameter).

  • 'STACKED': GS1 DataBar Stacked (n=72)
  • 'STACKED-OMNIDIRECTIONAL': GS1 DataBar Stacked Omnidirectional (n=73)
  • 'EXPANDED-STACKED': GS1 DataBar Expanded Stacked (n=76)

CompositeLineBarcode

enum CompositeLineBarcode {
  'EAN8' | 'EAN13' | 'UPC-A' | 'UPC-E' | 'UPC-E-FULL' |
  'GS1-DATABAR' | 'GS1-128'
}

CompositeLineBarcode represents the linear barcode type for a Composite Symbology line element (fn480, a=48).

| b | Value | | --- | -------------- | | 65 | 'EAN8' | | 66 | 'EAN13' | | 67 | 'UPC-A' | | 68 | 'UPC-E' | | 69 | 'UPC-E-FULL' | | 77 | 'GS1-128' |

When b=70–76, the barcode is 'GS1-DATABAR' and a CompositeGS1DataBarVariant is also present.

CompositeGS1DataBarVariant

enum CompositeGS1DataBarVariant {
  'OMNIDIRECTIONAL' | 'TRUNCATED' | 'STACKED' |
  'STACKED-OMNIDIRECTIONAL' | 'LIMITED' |
  'EXPANDED' | 'EXPANDED-STACKED'
}

CompositeGS1DataBarVariant represents the GS1 DataBar variant within a Composite Symbology line element.

| b | Value | | --- | --------------------------- | | 70 | 'OMNIDIRECTIONAL' | | 71 | 'TRUNCATED' | | 72 | 'STACKED' | | 73 | 'STACKED-OMNIDIRECTIONAL' | | 74 | 'LIMITED' | | 75 | 'EXPANDED' | | 76 | 'EXPANDED-STACKED' |

Composite2DSymbology

enum Composite2DSymbology {
  'AUTO' | 'CC-C'
}

Composite2DSymbology represents the 2D element type for a Composite Symbology (fn480, a=49).

| b | Value | | --- | -------- | | 65 | 'AUTO' | | 66 | 'CC-C' |

DrawerPin

enum DrawerPin {
  'pin2' | 'pin5'
}

DrawerPin represents cash drawer connector pin.

  • 'pin2': Drawer kick-out connector pin 2
  • 'pin5': Drawer kick-out connector pin 5

HriFont

enum HriFont {
  'A' | 'B'
}

HriFont represents the font for barcode HRI (Human Readable Interpretation) text.

Content model

type FlowContent = FlowBlockContent | PhrasingContent

Each node in epos-ast falls into one or more categories of Content that group nodes with similar characteristics together.

PhrasingContent

type PhrasingContent =
  Text | Break | Tab | Strong | Underline | Inverted | Scaled | Rotated |
  UpsideDown | Smoothing | DoubleStrike | Font | Color | Position | Raw

Phrasing content represents the text in a receipt and its markup.

FlowBlockContent

type FlowBlockContent =
  Align | LineSpacing | CharacterSpacing |
  Margin | PrintArea | TabStops | Feed | Cut | Pulse |
  Image | Barcode | QRCode | PDF417 | DataMatrix | MaxiCode | AztecCode |
  GS1DataBar | Composite

Flow block content represents structural elements of a receipt.

FlowContent

Flow content represents all content in an epos-ast tree. It is the union of flow block and phrasing content.

Serialization

Parsing

Parsing converts ESC/POS binary data to an epos-ast tree.

The parser maintains state for:

  • Current codepage
  • Current international character set
  • Active formatting (bold, underline, etc.)
  • Alignment
  • Font

When a formatting command is encountered (e.g., ESC E 1 for bold ON), the parser opens a new parent node. When the corresponding OFF command is encountered (ESC E 0), the parser closes that node.

Codepage (ESC t) and international character set (ESC R) commands update parser state. The parser decodes text bytes to Unicode using the current codepage/country, and stores these values on each Text node. This makes text nodes self-contained and easy to manipulate.

The printer reset command (ESC @) is handled internally by the parser. When encountered, it resets all parser state (codepage, formatting, alignment, etc.) to defaults without emitting a node. This is equivalent to starting a new print job.

Input bytes: 1B 45 01 48 65 6C 6C 6F 1B 45 00
             │         │           │
             │         │           └─ ESC E 0 (bold off)
             │         └─ "Hello"
             └─ ESC E 1 (bold on)

Output AST:
{
  type: 'root',
  children: [
    {
      type: 'strong',
      children: [
        { type: 'text', value: 'Hello' }
      ]
    }
  ]
}

Stringifying

Stringifying converts an epos-ast tree back to ESC/POS binary data.

Each node type has a corresponding byte sequence documented in its "Yields" section. The stringifier maintains state to properly restore settings after nested nodes close.

For Text nodes, the stringifier tracks the current codepage/country and emits ESC t / ESC R commands only when they change. Text is encoded to bytes using the codepage specified on each node (or the default CP858 if not specified).

Round-trip guarantees

Semantic equivalence: stringify(parse(bytes)) produces bytes that, when printed, produce visually identical output.

Not guaranteed: Byte-identical round-trip. Different command sequences can produce the same visual result. The parser normalizes to canonical forms.

Guaranteed: No information loss for recognized commands. Unknown commands preserved via Raw nodes produce identical bytes.

Codepage reference

| Code | Name | Description | | ---- | ---------- | ----------------------------- | | 0 | PC437 | USA, Standard Europe | | 1 | Katakana | Katakana | | 2 | PC850 | Multilingual | | 3 | PC860 | Portuguese | | 4 | PC863 | Canadian-French | | 5 | PC865 | Nordic | | 6 | Hiragana | Hiragana | | 7 | Kanji | One-pass printing Kanji | | 8 | Kanji | One-pass printing Kanji | | 11 | PC851 | Greek | | 12 | PC853 | Turkish | | 13 | PC857 | Turkish | | 14 | PC737 | Greek | | 15 | ISO8859-7 | Greek | | 16 | WPC1252 | Windows Latin 1 | | 17 | PC866 | Cyrillic #2 | | 18 | PC852 | Latin 2 | | 19 | PC858 | Euro (default) | | 20 | Thai42 | Thai Character Code 42 | | 21 | Thai11 | Thai Character Code 11 | | 22 | Thai13 | Thai Character Code 13 | | 23 | Thai14 | Thai Character Code 14 | | 24 | Thai16 | Thai Character Code 16 | | 25 | Thai17 | Thai Character Code 17 | | 26 | Thai18 | Thai Character Code 18 | | 30 | TCVN-3 | Vietnamese | | 31 | TCVN-3 | Vietnamese | | 32 | PC720 | Arabic | | 33 | WPC775 | Baltic Rim | | 34 | PC855 | Cyrillic | | 35 | PC861 | Icelandic | | 36 | PC862 | Hebrew | | 37 | PC864 | Arabic | | 38 | PC869 | Greek | | 39 | ISO8859-2 | Latin 2 | | 40 | ISO8859-15 | Latin 9 | | 41 | PC1098 | Farsi | | 42 | PC1118 | Lithuanian | | 43 | PC1119 | Lithuanian | | 44 | PC1125 | Ukrainian | | 45 | WPC1250 | Latin 2 | | 46 | WPC1251 | Cyrillic | | 47 | WPC1253 | Greek | | 48 | WPC1254 | Turkish | | 49 | WPC1255 | Hebrew | | 50 | WPC1256 | Arabic | | 51 | WPC1257 | Baltic Rim | | 52 | WPC1258 | Vietnamese | | 53 | KZ-1048 | Kazakhstan | | 66 | Devanagari | India (Hindi, Sanskrit, etc.) | | 67 | Bengali | India (Bengali, Assamese) | | 68 | Tamil | India (Tamil) | | 69 | Telugu | India (Telugu) | | 70 | Assamese | India (Assamese) | | 71 | Oriya | India (Odia) | | 72 | Kannada | India (Kannada) | | 73 | Malayalam | India (Malayalam) | | 74 | Gujarati | India (Gujarati) | | 75 | Punjabi | India (Punjabi/Gurmukhi) | | 82 | Marathi | India (Marathi) | | 254 | Page 254 | User-defined | | 255 | Page 255 | User-defined |

Unsupported

The following commands are unsupported due to unlikelihood of use or being status/control commands handled by the parser directly, not the document AST.

| Command | Description | | ------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | CAN | Cancel print data in page mode | | CR | Print and carriage return | | DLE DC4 | Real-time commands | | DLE ENQ | Send real-time request to printer | | DLE EOT | Transmit real-time status | | ESC % | Select/cancel user-defined characters | | ESC & | Define user-defined characters | | ESC * | Select bit-image mode | | ESC < | Return home | | ESC = | Select peripheral device | | ESC ( A | Execute beeper buzzer | | ESC ? | Cancel user-defined characters | | ESC FF | Print data in page mode | | ESC K | Print and reverse feed | | ESC L | Select page mode | | ESC S | Select standard mode | | ESC T | Select print direction in page mode | | ESC U | Turn unidirectional print mode on/off | | ESC W | Set print area in page mode | | ESC c 3 | Select paper sensor(s) to output paper-end signals | | ESC c 4 | Select paper sensor(s) to stop printing | | ESC c 5 | Enable/disable panel buttons | | ESC u | Transmit peripheral device status | | ESC v | Transmit paper sensor status | | ESC ( Y | Specify batch print | | FF | Form feed (page mode / end job) | | FS ! | Select print mode(s) for Kanji | | FS & | Select Kanji character mode | | FS ( A | Select Kanji character style(s) | | FS ( C | Select code conversion method | | FS ( E | Receipt enhancement control (top/bottom logo) | | FS ( L | Label and black mark control | | FS ( e | Enable/disable ASB for optional functions | | FS - | Turn underline on/off for Kanji | | FS . | Cancel Kanji character mode | | FS 2 | Define user-defined Kanji characters | | FS ? | Cancel user-defined Kanji characters | | FS C | Select Kanji character code system | | FS S | Set Kanji character spacing | | FS W | Turn quadruple-size on/off for Kanji | | FS g 1 | Write to NV user memory | | FS g 2 | Read from NV user memory | | FS p | Print NV bit image | | FS q | Define NV bit image | | GS $ | Set absolute vertical print position in page mode | | GS ( A | Execute test print | | GS ( C | Edit NV user memory | | GS ( D | Enable/disable real-time command | | GS ( E | Set user setup commands | | GS ( H | Request transmission of response or status | | GS ( K | Select print control method(s) | | GS ( L fn=48-52 | Graphics memory capacity/density | | GS ( L fn=64-69 | NV graphics storage | | GS ( L fn=80-85 | Download graphics storage | | GS ( L fn=113 | Store graphics data (column format) | | GS ( M | Customize printer control value(s) | | GS ( N | Select character effects | | GS ( P | Page mode control | | GS ( Q | Draw line/rectangle (page mode) | | GS ( V | Specify paper cut | | GS ( k fn=082 | PDF417 transmit size information | | GS ( k fn=182 | QR Code transmit size information | | GS ( k fn=282 | MaxiCode transmit size information | | GS ( k fn=382 | GS1 DataBar transmit size information | | GS ( k fn=482 | Composite transmit size information | | GS ( k fn=582 | Aztec Code transmit size information | | GS ( k fn=682 | DataMatrix transmit size information | | GS * | Define downloaded bit image | | GS / | Print downloaded bit image | | GS : | Start/end macro definition | | GS C 0 | Select counter print mode | | GS C 1 | Select count mode (A) | | GS C 2 | Set counter | | GS C ; | Select count mode (B) | | GS D | Specify Windows BMP graphics data | | GS I | Transmit printer ID | | GS P | Set horizontal and vertical motion units | | GS Q 0 | Print variable vertical size bit image | | GS T | Set print position to beginning of print line | | GS \ | Set relative vertical print position in page mode | | GS ^ | Execute macro | | GS a | Enable/disable ASB | | GS c | Print counter | | GS g 0 | Initialize maintenance counter | | GS g 2 | Transmit maintenance counter | | GS j | Enable/disable ASB for ink | | GS r | Transmit status | | GS v 0 | Print raster bit image | | GS z 0 | Set online recovery wait time |

Unit system

epos-ast uses dots at 203 DPI as the canonical unit for all distance and position values. This provides:

  • Integer math — no floating-point rounding errors
  • Common baseline — 203 DPI matches the majority of modern thermal printers
  • Portability — AST values are independent of source printer motion unit configuration

Motion units in ESC/POS

ESC/POS printers use configurable "motion units" set by GS P. The x parameter controls horizontal commands, y controls vertical commands. The physical distance per unit is 25.4/x mm horizontally and 25.4/y mm vertically.

| Printer family | Default x | Default y | Horizontal | Vertical | Notes | | -------------------------------------------------------------------- | --------- | --------- | ---------- | -------- | -------------------- | | TM-m30 series, TM-m50, EU-m30, TM-L90, TM-L100, TM-m10 | 203 | 406 | 0.125mm | 0.063mm | | | TM-T20 series, TM-T81III, TM-T82 series, TM-T83 series, TM-T100 | 203 | 406 | 0.125mm | 0.063mm | standard column mode | | TM-T20 series, TM-T82 series (42-column mode) | 180 | 360 | 0.141mm | 0.071mm | | | TM-T88IV, TM-T88V, TM-T88VI, TM-T88VII, TM-J2000, TM-J2100, TM-m50II | 180 | 360 | 0.141mm | 0.071mm | | | TM-P20, TM-P20II | 203 | 203 | 0.125mm | 0.125mm | 1:1 ratio | | TM-P80, TM-P80II (48-column) | 203 | 203 | 0.125mm | 0.125mm | | | TM-P80, TM-P80II (42-