/** * Compiler Types * Type definitions for document compilation and ESC/POS protocol */ import {ImageOptions} from '../printer' /** * Document Node Types * High-level document structure for thermal printing */ export type Node = | TextNode | LineNode | QRNode | BarcodeNode | ImageNode | FeedNode | CutNode | RawNode | ColumnsNode | TableNode | SpacerNode export interface TextNode { type: 'text' content: string style?: TextStyle } export interface TextStyle { align?: PrintAlignment font?: PrintFont size?: PrintSize bold?: boolean underline?: boolean doubleStrike?: boolean reverse?: boolean strikethrough?: boolean // Add strikethrough line above text (manual dash line) wrap?: boolean // Auto wrap long text maxWidth?: number // Max width in characters before wrapping marginLeft?: number // Left margin in characters (overrides global margin for this node) marginRight?: number // Right margin in characters (overrides global margin for this node) } export interface LineNode { type: 'line' style?: 'solid' | 'dashed' | 'double' | 'equals' character?: string widthChars?: number // Width in characters (auto-calculated from paperWidthMm if not set) marginLeft?: number // Left margin in characters marginRight?: number // Right margin in characters } export interface QRNode { type: 'qr' content: string size?: number errorLevel?: 'L' | 'M' | 'Q' | 'H' align?: PrintAlignment // QR alignment: 'left', 'center', 'right' (default: 'center') marginLeft?: number // Left margin in characters marginRight?: number // Right margin in characters } export interface BarcodeNode { type: 'barcode' content: string format?: 'CODE39' | 'CODE128' | 'EAN13' | 'EAN8' | 'UPC_A' heightPx?: number // Height in pixels widthPx?: number // Width in pixels (barcode bar width, not paper width) textPosition?: 'none' | 'above' | 'below' | 'both' align?: PrintAlignment // Barcode alignment: 'left', 'center', 'right' (default: 'center') marginLeft?: number // Left margin in characters marginRight?: number // Right margin in characters } export interface ImageNode { type: 'image' imagePath: string options?: ImageOptions } export interface FeedNode { type: 'feed' lines?: number } export interface CutNode { type: 'cut' partial?: boolean forceCut?: boolean // Force cut even in label mode (default: false) } export interface RawNode { type: 'raw' data: number[] } /** * Columns Node for multi-column layout */ export interface ColumnsNode { type: 'columns' columns: ColumnData[] separator?: string // Optional separator between columns style?: TextStyle // Global style for all columns (can be overridden per column) } export interface ColumnData { content: string width?: number // Width in percentage (0-100) or fixed characters align?: PrintAlignment style?: TextStyle // Per-column style (overrides global style) } /** * Border style types for table */ export type BorderStyle = 'none' | 'solid' | 'dashed' | 'double' export type BorderCharSet = 'ascii' | 'utf8' /** * Table border configuration */ export interface TableBorderConfig { // Horizontal borders top?: boolean | BorderStyle bottom?: boolean | BorderStyle header?: boolean | BorderStyle // After header row between?: boolean | BorderStyle // Between data rows // Vertical borders left?: boolean | BorderStyle // Left table edge right?: boolean | BorderStyle // Right table edge columns?: boolean | BorderStyle // Between columns } /** * Custom border characters (for box drawing) */ export interface TableBorderChars { horizontal?: string // Horizontal line: '-' or '─' vertical?: string // Vertical line: '|' or '│' topLeft?: string // Top-left corner: '+' or '┌' topRight?: string // Top-right corner: '+' or '┐' topJunction?: string // Top T-junction: '+' or '┬' leftJunction?: string // Left T-junction: '+' or '├' rightJunction?: string // Right T-junction: '+' or '┤' cross?: string // Cross junction: '+' or '┼' bottomLeft?: string // Bottom-left corner: '+' or '└' bottomRight?: string // Bottom-right corner: '+' or '┘' bottomJunction?: string // Bottom T-junction: '+' or '┴' } /** * Table Cell - can be simple string or rich object with styling * * IMPORTANT: Per-cell style has limitations due to ESC/POS hardware: * - Font and size apply to the ENTIRE ROW (uses first cell's font/size) * - Bold, underline, reverse can vary per-cell (future enhancement) * - For different font/size per cell, use multiple text nodes instead of table */ export type TableCell = | string | { text: string strikethrough?: string // Original price to display with strikethrough (e.g., "120.000" when text is "50.000") style?: TextStyle // Per-cell style (font/size apply to entire row, from first cell) } /** * Table Node for structured data (for product lists, reports) */ export interface TableNode { type: 'table' headers?: TableCell[] rows: TableCell[][] columnWidths?: number[] // Width percentages (0-100) alignments?: PrintAlignment[] // Alignment for each column border?: TableBorderConfig // Border character set: 'ascii' (default, safe) or 'utf8' (box drawing) borderCharSet?: BorderCharSet // Custom border characters (overrides defaults from borderCharSet) borderChars?: TableBorderChars // Enable text wrapping for cells (default: false) wrapCells?: boolean headerStyle?: TextStyle // Style for headers cellStyle?: TextStyle // Style for all data cells marginLeft?: number // Left margin in characters marginRight?: number // Right margin in characters } /** * Spacer Node for dynamic spacing */ export interface SpacerNode { type: 'spacer' height?: number // Height in lines fill?: string // Optional fill character } export type PrintAlignment = 'left' | 'center' | 'right' export type PrintFont = 'A' | 'B' /** * Print size - controls character size (uniform width x height multiplier) * * Maps directly to ESC/POS GS ! command (1x1 to 8x8) * * Supported values: * - 1: 1x1 (smallest size) * - 2: 2x2 * - 3: 3x3 * - 4: 4x4 * - 5: 5x5 * - 6: 6x6 * - 7: 7x7 * - 8: 8x8 (largest size supported by ESC/POS) * * Note: Size changes both width and height uniformly. * If size is not specified, printer uses default (typically 1x1). * For asymmetric scaling, use raw ESC/POS commands via RawNode. */ export type PrintSize = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 /** * Compilation Context * Runtime context for document compilation */ export interface CompileContext { paperWidthMm: number // Paper width in millimeters (common: 32, 40, 50, 58, 60, 80) paperWidthChars: number // Paper width in characters (auto-calculated from paperWidthMm and currentFont) encoding: EncodingType codepage?: number // Custom ESC/POS codepage number (optional) marginMm: number // Global margin in mm (default: 1mm each side) lineSpacing: number // Line spacing in 1/180 inch units (default: 60) currentFont: PrintFont // Current font being used (default: 'A') - updated when text nodes change font printerType?: 'receipt' | 'label' // Printer type (default: 'receipt') labelGapMm?: number // Gap between labels in mm (default: 2mm) labelHeightMm?: number // Label height in mm (for overflow detection) disableCutPaper?: boolean // Disable cut paper command (for label printers) } /** * Encoding types: UTF-8 (default) or ASCII (removes Vietnamese tones) */ export type EncodingType = 'utf8' | 'ascii'