use hardless_escpos::{Align, Node};
use crate::codes;
use crate::html::symbology_name;
use crate::layout::{layout, Block, Segment};
use crate::RenderOptions;
pub fn to_text(nodes: &[Node]) -> String {
to_text_with(nodes, &RenderOptions::default())
}
pub fn to_text_with(nodes: &[Node], options: &RenderOptions) -> String {
let (columns_a, columns_b) = options.paper.columns();
let mut out = String::new();
for block in layout(nodes, options.paper, false) {
match block {
Block::Line(line) => {
let text: String = line
.segments
.iter()
.filter_map(|s| match s {
Segment::Text { text, .. } => Some(text.as_str()),
Segment::Unknown { .. } => None,
})
.collect();
let used = line.columns.div_ceil(columns_b.max(1));
push_aligned(&mut out, line.align, &text, used, columns_a);
}
Block::Cut { .. } => {}
Block::Qr { align, text, .. } => {
let label = format!("[QR: {}]", printable(&text));
push_label(&mut out, align, &label, columns_a);
}
Block::Barcode {
align,
symbology,
data,
..
} => {
let label = format!(
"[BARCODE {}: {}]",
symbology_name(symbology),
printable(&codes::barcode_text(symbology, &data))
);
push_label(&mut out, align, &label, columns_a);
}
Block::Image {
align,
width_bytes,
height,
double_width,
double_height,
..
} => {
let w = u32::from(width_bytes) * 8 * if double_width { 2 } else { 1 };
let h = u32::from(height) * if double_height { 2 } else { 1 };
push_label(&mut out, align, &format!("[IMAGE {w}x{h}]"), columns_a);
}
}
}
out
}
fn push_label(out: &mut String, align: Align, label: &str, columns: u32) {
let used = u32::try_from(label.chars().count()).unwrap_or(u32::MAX);
push_aligned(out, align, label, used, columns);
}
fn push_aligned(out: &mut String, align: Align, text: &str, used: u32, columns: u32) {
let free = columns.saturating_sub(used);
let pad = match align {
Align::Left => 0,
Align::Center => free / 2,
Align::Right => free,
};
let line = format!("{}{}", " ".repeat(pad as usize), text);
out.push_str(line.trim_end());
out.push('\n');
}
fn printable(text: &str) -> String {
text.chars()
.map(|c| if c.is_control() { '\u{fffd}' } else { c })
.collect()
}