zpl-js-helper
Version:
A package that is intended to help with the creation of ZPL labels and templates using JS, with scalable text sizes to prevent overflow and overlap of text.
379 lines (370 loc) • 10.9 kB
JavaScript
// src/components/density.ts
var PrintDensity = /* @__PURE__ */ ((PrintDensity2) => {
PrintDensity2[PrintDensity2["8dpmm"] = 8] = "8dpmm";
return PrintDensity2;
})(PrintDensity || {});
// src/components/size.ts
var Size = class {
constructor(widthInDots, heightInDots) {
this.widthInDots = widthInDots;
this.heightInDots = heightInDots;
}
};
// src/components/template.ts
var Template = class {
constructor(widthInMM, heightInMM, dotsPerMM = 8 /* 8dpmm */) {
this.sections = [];
this.dotsPerMM = dotsPerMM;
const size = new Size(widthInMM * this.dotsPerMM, heightInMM * this.dotsPerMM);
this.size = size;
}
generateTestZpl() {
const start = "^XA";
const end = "^XZ";
const borderBox = `
^PW${this.size.widthInDots.toString()}
^LL${this.size.heightInDots.toString()}
^FWR
^FO0,0
^GB${this.size.heightInDots.toString()},${this.size.widthInDots.toString()},5^FS
^FB
^FDTEST^FS
`;
return start + borderBox + end;
}
addZPLSection(zplSection) {
this.sections.push(zplSection);
}
getSections() {
return this.sections;
}
};
// src/components/origin.ts
var Origin = class {
constructor(orginXInDots, orginYInDots) {
if (orginXInDots < 0 || orginYInDots < 0)
throw new Error("Origin cannot have negative values.");
this.originXInDots = orginXInDots;
this.originYInDots = orginYInDots;
}
};
// src/components/text-line.ts
var TextLine = class {
constructor(text) {
this.text = text;
}
};
// src/components/padding.ts
var Padding = class {
constructor(top, bottom, left, right) {
this.top = 0;
this.bottom = 0;
this.left = 0;
this.right = 0;
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
}
totalX() {
return this.left + this.right;
}
totalY() {
return this.top + this.bottom;
}
};
// src/components/text-section.ts
var TextSection = class {
// Constructor with parameters for all the properties
constructor(fontFamily, size, origin, sectionKey, border = "none", borderThickness = 2, padding = new Padding(0, 0, 0, 0), orientation = "portrait", textAlignment = "J", fontSize = 30) {
this.defaultFontSize = 30;
this.fontFamily = fontFamily;
this.padding = padding;
this.size = size;
this.origin = origin;
this.sectionKey = sectionKey;
this.border = border;
this.borderThickness = borderThickness;
this.orientation = orientation;
this.textAlignment = textAlignment;
this.defaultFontSize = fontSize;
}
// Method to generate ZPL string
generateZpl(values = []) {
const content = this.generateText(values);
const border = this.generateSectionBorders();
return content + border;
}
// Method to generate borders for the section based on the border property
generateSectionBorders() {
let zpl = "";
const borderThickness = this.borderThickness;
if (this.border === "top" || this.border === "all") {
zpl += `^FO${this.origin.originXInDots},${this.origin.originYInDots}\r
^GB${this.size.widthInDots},${borderThickness},${borderThickness}^FS\r
`;
}
if (this.border === "bottom" || this.border === "all") {
zpl += `^FO${this.origin.originXInDots},${this.origin.originYInDots + this.size.heightInDots - borderThickness}\r
^GB${this.size.widthInDots},${borderThickness},${borderThickness}^FS\r
`;
}
if (this.border === "left" || this.border === "all") {
zpl += `^FO${this.origin.originXInDots},${this.origin.originYInDots}\r
^GB${borderThickness},${this.size.heightInDots},${borderThickness}^FS\r
`;
}
if (this.border === "right" || this.border === "all") {
zpl += `^FO${this.origin.originXInDots + this.size.widthInDots - borderThickness},${this.origin.originYInDots}\r
^GB${borderThickness},${this.size.heightInDots},${borderThickness}^FS\r
`;
}
return zpl;
}
generateText(values = []) {
if (values.length === 0) {
return "";
}
let zpl = this.orientation == "landscape" ? "^CI28\r\n^FWB\r\n" : "^CI28\r\n^FWN\r\n";
const totalLengthX = this.size.widthInDots - this.padding.totalX();
const totalLengthY = this.size.heightInDots - this.padding.totalY();
const availableHeight = this.orientation == "landscape" ? totalLengthX : totalLengthY;
const availableWidth = this.orientation == "landscape" ? totalLengthY : totalLengthX;
const result = this.processTextUpdated(
values,
availableWidth,
this.defaultFontSize
);
const textLines = result.lines;
const adjustedFontSize = result.fontSize;
const fontSize = Math.min(
adjustedFontSize,
Math.floor(availableHeight / textLines.length)
);
const textAlignmentEscape = this.textAlignment == "C" ? "\\&" : "";
for (let i = 0; i < textLines.length; i++) {
const textOriginX = this.orientation == "landscape" ? i * fontSize + this.origin.originXInDots + this.padding.left : this.origin.originXInDots + this.padding.left;
const textOriginY = this.orientation == "landscape" ? this.origin.originYInDots + this.padding.top : i * fontSize + this.padding.top + this.origin.originYInDots;
zpl += `^FO ${textOriginX},${textOriginY}\r
^A${this.fontFamily.toString()},${fontSize} ${this.fontFamily == "0" ? "," + fontSize.toString() : ""}\r
^FB${this.orientation == "landscape" ? totalLengthY : totalLengthX},,5,${this.textAlignment}
^FD${textLines[i]}${textAlignmentEscape}^FS\r
`;
}
return zpl;
}
processText(text, availableWidth) {
const processedLines = [];
const scaleFactor = this.fontFamily == "0" ? 2 : 1.25;
text.forEach((line) => {
const words = line.split(" ");
let currentLine = "";
words.forEach((word) => {
const testLine = currentLine ? `${currentLine} ${word}` : word;
console.log(
`Available Width: ${availableWidth}
Testline: ${testLine}
Testline width: ${this.calculateStringLengthRelativeToCharacters(testLine) * this.defaultFontSize}`
);
if (this.calculateStringLengthRelativeToCharacters(testLine) * (this.defaultFontSize / scaleFactor) <= availableWidth) {
currentLine = testLine;
} else {
if (currentLine) processedLines.push(currentLine);
currentLine = word;
}
});
if (currentLine) processedLines.push(currentLine);
});
return processedLines;
}
calculateStringLengthRelativeToCharacters(text) {
const charWidths = {
" ": 117,
"!": 113,
'"': 183,
"#": 183,
$: 183,
"%": 366,
"&": 235,
"'": 113,
"(": 113,
")": 113,
"*": 183,
"+": 330,
",": 110,
"-": 200,
".": 113,
"/": 113,
"0": 183,
"1": 183,
"2": 183,
"3": 183,
"4": 183,
"5": 183,
"6": 183,
"7": 183,
"8": 183,
"9": 183,
":": 117,
";": 117,
"<": 366,
"=": 366,
">": 366,
"?": 165,
"@": 330,
A: 220,
B: 220,
C: 206,
D: 235,
E: 194,
F: 194,
G: 220,
H: 235,
I: 110,
J: 173,
K: 220,
L: 183,
M: 300,
N: 235,
O: 220,
P: 220,
Q: 220,
R: 220,
S: 206,
T: 183,
U: 235,
V: 206,
W: 300,
X: 206,
Y: 206,
Z: 194,
"[": 113,
"\\": 192,
"]": 113,
"^": 192,
_: 194,
"`": 113,
a: 173,
b: 194,
c: 173,
d: 194,
e: 183,
f: 106,
g: 194,
h: 194,
i: 100,
j: 100,
k: 173,
l: 100,
m: 300,
n: 194,
o: 183,
p: 194,
q: 194,
r: 126,
s: 165,
t: 106,
u: 194,
v: 173,
w: 253,
x: 173,
y: 173,
z: 150,
"{": 194,
"|": 194,
"}": 194,
"~": 192
};
let relativeStringLength = 0;
for (const char of text) {
relativeStringLength += charWidths[char] || 192;
}
return relativeStringLength / 192;
}
processTextUpdated(lines, availableWidth, desiredFontSize) {
let fontSize = desiredFontSize;
const minFontSize = this.fontFamily == "0" ? 20 : 20;
const scaleFactor = this.fontFamily == "0" ? 2 : this.fontFamily == "C" ? 1.25 : 1.25;
let maxLineWidth = Math.max(
...lines.map(
(line) => this.calculateStringLengthRelativeToCharacters(line) * (fontSize / scaleFactor)
)
);
console.log(lines, maxLineWidth, availableWidth);
while (maxLineWidth > availableWidth && fontSize > minFontSize) {
fontSize -= 1;
maxLineWidth = Math.max(
...lines.map(
(line) => this.calculateStringLengthRelativeToCharacters(line) * (fontSize / scaleFactor)
)
);
}
if (fontSize <= minFontSize && maxLineWidth > availableWidth) {
lines = this.breakUpLines(
lines,
availableWidth,
minFontSize,
scaleFactor
);
}
return { lines, fontSize };
}
breakUpLines(lines, availableWidth, fontSize, scaleFactor) {
const processedLines = [];
lines.forEach((line) => {
const words = line.split(" ");
let currentLine = "";
words.forEach((word) => {
const testLine = currentLine ? `${currentLine} ${word}` : word;
if (this.calculateStringLengthRelativeToCharacters(testLine) * (fontSize / scaleFactor) <= availableWidth) {
currentLine = testLine;
} else {
if (currentLine) processedLines.push(currentLine);
currentLine = word;
}
});
if (currentLine) processedLines.push(currentLine);
});
return processedLines;
}
};
// src/components/label-builder.ts
var LabelBuilder = class {
constructor(template, records) {
this.template = template;
this.records = records;
}
// This method will generate ZPL for all records based on the template sections
generateZPL() {
const start = "^XA\r\n";
const setup = `^PW${this.template.size.widthInDots.toString()}\r
^LL${this.template.size.heightInDots.toString()}\r
`;
const end = "^XZ";
let zplCode = "";
this.records.forEach((record) => {
const content = this.template.getSections().map((section) => this.generateSectionZPL(section, record)).join("\r\n");
const zplCodeForSection = start + setup + content + end;
zplCode += zplCodeForSection;
});
return zplCode;
}
// Method to generate ZPL for each section based on the current record
generateSectionZPL(section, record) {
if (record[section.sectionKey]) {
return section.generateZpl(record[section.sectionKey]);
}
return "";
}
};
export {
LabelBuilder,
Origin,
Padding,
PrintDensity,
Size,
Template,
TextLine,
TextSection
};
//# sourceMappingURL=index.js.map