@worm-vue3-print/core 1.3.8 → 1.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.cjs +281 -44
- package/dist/browser/index.d.cts +3 -3
- package/dist/browser/index.d.ts +3 -3
- package/dist/browser/index.js +33 -30
- package/dist/{chunk-ZKHVOCU5.js → chunk-4ZEP2HSH.js} +2 -2
- package/dist/{chunk-TQJGFV2V.js → chunk-7FXIWNYK.js} +367 -19
- package/dist/client/index.cjs +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/designer/index.cjs +719 -19
- package/dist/designer/index.d.cts +357 -9
- package/dist/designer/index.d.ts +357 -9
- package/dist/designer/index.js +458 -8
- package/dist/dom-executor.iife.global.js +7 -7
- package/dist/{driver-hJxBl2_n.d.cts → driver-DW3mxuRF.d.cts} +87 -5
- package/dist/{driver-hJxBl2_n.d.ts → driver-DW3mxuRF.d.ts} +87 -5
- package/dist/index.cjs +242 -8
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +15 -3
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +2 -2
- package/dist/node/index.d.ts +2 -2
- package/dist/node/index.js +1 -1
- package/dist/{ports-B-Jb2XwT.d.cts → ports-Brn5xcLD.d.ts} +2 -2
- package/dist/{ports-CJ0SUYFt.d.ts → ports-DJ7_blE7.d.cts} +2 -2
- package/package.json +1 -1
package/dist/browser/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @worm-vue3-print/core v1.3.
|
|
2
|
+
* @worm-vue3-print/core v1.3.10
|
|
3
3
|
* Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
|
|
4
4
|
* SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
@@ -200,9 +200,13 @@ var import_qrcode = __toESM(require("qrcode"), 1);
|
|
|
200
200
|
// src/render/barcode-dot.ts
|
|
201
201
|
var MM_PER_INCH = 25.4;
|
|
202
202
|
var BARCODE_QUIET_ZONE_MODULES = 10;
|
|
203
|
+
function barcodeQuietZoneModules(value) {
|
|
204
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : BARCODE_QUIET_ZONE_MODULES;
|
|
205
|
+
}
|
|
203
206
|
var BARCODE_BAR_HEIGHT_MODULES = 30;
|
|
204
207
|
var BARCODE_TEXT_FONT_SIZE_MODULES = 10;
|
|
205
208
|
var BARCODE_MARGIN_BOTTOM_MODULES = 2;
|
|
209
|
+
var QR_DEFAULT_QUIET_MODULES = 0;
|
|
206
210
|
var BARCODE_MODULE_WIDTH_MM = 0.25;
|
|
207
211
|
function barcodeUnitsPerModule(barWidth) {
|
|
208
212
|
const raw = typeof barWidth === "number" && Number.isFinite(barWidth) ? barWidth : 2;
|
|
@@ -211,6 +215,36 @@ function barcodeUnitsPerModule(barWidth) {
|
|
|
211
215
|
function barcodePreferredModuleWidthMm(barWidth) {
|
|
212
216
|
return barcodeUnitsPerModule(barWidth) * BARCODE_MODULE_WIDTH_MM;
|
|
213
217
|
}
|
|
218
|
+
function barcodeBarHeightModules(input) {
|
|
219
|
+
const { barHeightMm, moduleWidthMm, boxHeightMm, textModules } = input;
|
|
220
|
+
const hasHeight = typeof barHeightMm === "number" && Number.isFinite(barHeightMm) && barHeightMm > 0;
|
|
221
|
+
const hasGranularity = typeof moduleWidthMm === "number" && Number.isFinite(moduleWidthMm) && moduleWidthMm > 0;
|
|
222
|
+
if (!hasHeight || !hasGranularity) return BARCODE_BAR_HEIGHT_MODULES;
|
|
223
|
+
const wanted = Math.max(1, Math.round(barHeightMm / moduleWidthMm));
|
|
224
|
+
const hasBox = typeof boxHeightMm === "number" && Number.isFinite(boxHeightMm) && boxHeightMm > 0;
|
|
225
|
+
if (!hasBox) return wanted;
|
|
226
|
+
const text = typeof textModules === "number" && Number.isFinite(textModules) && textModules > 0 ? textModules : 0;
|
|
227
|
+
const cap = Math.floor((boxHeightMm - text * moduleWidthMm) / moduleWidthMm);
|
|
228
|
+
return Math.max(1, Math.min(wanted, cap));
|
|
229
|
+
}
|
|
230
|
+
function dotAlignedModuleWidth(preferredMm, maxModuleMm, dotsPerMm) {
|
|
231
|
+
const preferredDots = Math.max(1, Math.round(preferredMm * dotsPerMm));
|
|
232
|
+
const maxDots = Math.floor(maxModuleMm * dotsPerMm);
|
|
233
|
+
if (maxDots < 1) return null;
|
|
234
|
+
const dotsPerModule = Math.min(preferredDots, maxDots);
|
|
235
|
+
return { dotsPerModule, preferredDots, moduleWidthMm: dotsPerModule / dotsPerMm };
|
|
236
|
+
}
|
|
237
|
+
function barcodeWidthBoundModuleWidthMm(input) {
|
|
238
|
+
const preferredMm = barcodePreferredModuleWidthMm(input.barWidth);
|
|
239
|
+
const unitWidth = Math.max(1, Math.ceil(input.unitWidth));
|
|
240
|
+
const maxModuleMm = input.boxWidthMm > 0 ? input.boxWidthMm / unitWidth : Number.POSITIVE_INFINITY;
|
|
241
|
+
const dpi = input.dpi;
|
|
242
|
+
if (typeof dpi === "number" && Number.isFinite(dpi) && dpi > 0) {
|
|
243
|
+
const aligned = dotAlignedModuleWidth(preferredMm, maxModuleMm, dpi / MM_PER_INCH);
|
|
244
|
+
if (aligned) return aligned.moduleWidthMm;
|
|
245
|
+
}
|
|
246
|
+
return Math.min(preferredMm, maxModuleMm);
|
|
247
|
+
}
|
|
214
248
|
function barcodeAvailableBoxMm(boxMm, maxMm) {
|
|
215
249
|
const box = typeof boxMm === "number" && boxMm > 0 ? boxMm : Number.POSITIVE_INFINITY;
|
|
216
250
|
const limit = typeof maxMm === "number" && maxMm > 0 ? Math.min(box, maxMm) : box;
|
|
@@ -226,18 +260,14 @@ function resolveBarcodeSize(input) {
|
|
|
226
260
|
);
|
|
227
261
|
const dpi = input.dpi;
|
|
228
262
|
if (typeof dpi === "number" && Number.isFinite(dpi) && dpi > 0) {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
const maxDots = Math.floor(maxModuleMm * dotsPerMm);
|
|
232
|
-
if (maxDots >= 1) {
|
|
233
|
-
const dotsPerModule = Math.min(preferredDots, maxDots);
|
|
234
|
-
const moduleWidthMm2 = dotsPerModule / dotsPerMm;
|
|
263
|
+
const aligned = dotAlignedModuleWidth(preferredModuleMm, maxModuleMm, dpi / MM_PER_INCH);
|
|
264
|
+
if (aligned) {
|
|
235
265
|
return {
|
|
236
|
-
moduleWidthMm:
|
|
237
|
-
widthMm: unitWidth *
|
|
238
|
-
heightMm: unitHeight *
|
|
239
|
-
dotsPerModule,
|
|
240
|
-
scaledDown: dotsPerModule < preferredDots
|
|
266
|
+
moduleWidthMm: aligned.moduleWidthMm,
|
|
267
|
+
widthMm: unitWidth * aligned.moduleWidthMm,
|
|
268
|
+
heightMm: unitHeight * aligned.moduleWidthMm,
|
|
269
|
+
dotsPerModule: aligned.dotsPerModule,
|
|
270
|
+
scaledDown: aligned.dotsPerModule < aligned.preferredDots
|
|
241
271
|
};
|
|
242
272
|
}
|
|
243
273
|
}
|
|
@@ -250,6 +280,39 @@ function resolveBarcodeSize(input) {
|
|
|
250
280
|
scaledDown: moduleWidthMm < preferredModuleMm
|
|
251
281
|
};
|
|
252
282
|
}
|
|
283
|
+
function layoutBarcodeSize(input) {
|
|
284
|
+
const upm = barcodeUnitsPerModule(input.barWidth);
|
|
285
|
+
const settle = (units) => resolveBarcodeSize({
|
|
286
|
+
unitWidth: units.widthUnits / upm,
|
|
287
|
+
unitHeight: units.heightUnits / upm,
|
|
288
|
+
boxWidthMm: input.boxWidthMm,
|
|
289
|
+
boxHeightMm: input.boxHeightMm,
|
|
290
|
+
dpi: input.dpi,
|
|
291
|
+
barWidth: input.barWidth
|
|
292
|
+
});
|
|
293
|
+
const first = input.measure(BARCODE_BAR_HEIGHT_MODULES);
|
|
294
|
+
if (!first) return { barHeightModules: BARCODE_BAR_HEIGHT_MODULES, size: null };
|
|
295
|
+
const hasHeight = typeof input.barHeightMm === "number" && Number.isFinite(input.barHeightMm) && input.barHeightMm > 0;
|
|
296
|
+
if (!hasHeight) return { barHeightModules: BARCODE_BAR_HEIGHT_MODULES, size: settle(first) };
|
|
297
|
+
const textModules = Math.max(0, first.heightUnits / upm - BARCODE_BAR_HEIGHT_MODULES);
|
|
298
|
+
const barHeightModules = barcodeBarHeightModules({
|
|
299
|
+
barHeightMm: input.barHeightMm,
|
|
300
|
+
moduleWidthMm: barcodeWidthBoundModuleWidthMm({
|
|
301
|
+
unitWidth: first.widthUnits / upm,
|
|
302
|
+
boxWidthMm: input.boxWidthMm,
|
|
303
|
+
dpi: input.dpi,
|
|
304
|
+
barWidth: input.barWidth
|
|
305
|
+
}),
|
|
306
|
+
boxHeightMm: input.boxHeightMm,
|
|
307
|
+
textModules
|
|
308
|
+
});
|
|
309
|
+
if (barHeightModules === BARCODE_BAR_HEIGHT_MODULES) {
|
|
310
|
+
return { barHeightModules, size: settle(first) };
|
|
311
|
+
}
|
|
312
|
+
const second = input.measure(barHeightModules);
|
|
313
|
+
if (!second) return { barHeightModules: BARCODE_BAR_HEIGHT_MODULES, size: null };
|
|
314
|
+
return { barHeightModules, size: settle(second) };
|
|
315
|
+
}
|
|
253
316
|
|
|
254
317
|
// src/browser/browser-code-renderer.ts
|
|
255
318
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
@@ -263,36 +326,39 @@ function readViewBox(svg) {
|
|
|
263
326
|
function renderBarcodeSvg(value, opts) {
|
|
264
327
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
265
328
|
const unitPerModule = barcodeUnitsPerModule(opts.barWidth);
|
|
266
|
-
(
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (viewBox) {
|
|
281
|
-
const size = resolveBarcodeSize({
|
|
282
|
-
unitWidth: viewBox.width / unitPerModule,
|
|
283
|
-
unitHeight: viewBox.height / unitPerModule,
|
|
284
|
-
boxWidthMm: opts.targetWidthMm ?? 0,
|
|
285
|
-
boxHeightMm: opts.targetHeightMm ?? 0,
|
|
286
|
-
dpi: opts.printerDpi,
|
|
287
|
-
barWidth: opts.barWidth
|
|
329
|
+
const quietModules = barcodeQuietZoneModules(opts.barQuietZone);
|
|
330
|
+
const measure = (barHeightModules) => {
|
|
331
|
+
(0, import_jsbarcode.default)(svg, value, {
|
|
332
|
+
format: opts.barcodeType || "CODE128",
|
|
333
|
+
width: unitPerModule,
|
|
334
|
+
height: barHeightModules * unitPerModule,
|
|
335
|
+
displayValue: opts.showText !== false,
|
|
336
|
+
fontSize: (opts.fontSize ?? BARCODE_TEXT_FONT_SIZE_MODULES) * unitPerModule,
|
|
337
|
+
// 静区只留左右:上下留白会白白吃掉元素高度(jsbarcode 的 margin 是四边通配)
|
|
338
|
+
margin: 0,
|
|
339
|
+
marginLeft: quietModules * unitPerModule,
|
|
340
|
+
marginRight: quietModules * unitPerModule,
|
|
341
|
+
marginTop: 0,
|
|
342
|
+
marginBottom: BARCODE_MARGIN_BOTTOM_MODULES * unitPerModule
|
|
288
343
|
});
|
|
289
|
-
svg
|
|
290
|
-
|
|
344
|
+
const viewBox = readViewBox(svg);
|
|
345
|
+
return viewBox ? { widthUnits: viewBox.width, heightUnits: viewBox.height } : null;
|
|
346
|
+
};
|
|
347
|
+
const layout = layoutBarcodeSize({
|
|
348
|
+
barHeightMm: opts.barHeightMm,
|
|
349
|
+
boxWidthMm: opts.targetWidthMm ?? 0,
|
|
350
|
+
boxHeightMm: opts.targetHeightMm ?? 0,
|
|
351
|
+
dpi: opts.printerDpi,
|
|
352
|
+
barWidth: opts.barWidth,
|
|
353
|
+
measure
|
|
354
|
+
});
|
|
355
|
+
if (layout.size) {
|
|
356
|
+
svg.setAttribute("width", `${layout.size.widthMm}mm`);
|
|
357
|
+
svg.setAttribute("height", `${layout.size.heightMm}mm`);
|
|
291
358
|
}
|
|
292
359
|
svg.setAttribute("shape-rendering", "crispEdges");
|
|
293
360
|
return svg.outerHTML;
|
|
294
361
|
}
|
|
295
|
-
var QR_DEFAULT_QUIET_MODULES = 0;
|
|
296
362
|
function qrQuietModules(value) {
|
|
297
363
|
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : QR_DEFAULT_QUIET_MODULES;
|
|
298
364
|
}
|
|
@@ -343,7 +409,9 @@ function normalizeFit(value) {
|
|
|
343
409
|
}
|
|
344
410
|
var ELEMENT_DEFAULT_FIT = {
|
|
345
411
|
text: "clip",
|
|
346
|
-
longText: "autoHeight"
|
|
412
|
+
longText: "autoHeight",
|
|
413
|
+
// 流式列表一框一页:超出元素框高的单元按截断处理,不自动撑破纸面(specs 第八节第 8 项)
|
|
414
|
+
flowList: "clip"
|
|
347
415
|
};
|
|
348
416
|
function resolveElementTextFit(type, opts) {
|
|
349
417
|
return normalizeFit(opts?.textFit) ?? ELEMENT_DEFAULT_FIT[type] ?? "clip";
|
|
@@ -1503,6 +1571,123 @@ function evaluateTemplate(text, ctx) {
|
|
|
1503
1571
|
}
|
|
1504
1572
|
}
|
|
1505
1573
|
|
|
1574
|
+
// src/render/flow-list.ts
|
|
1575
|
+
var FLOW_MIN_COLUMNS = 1;
|
|
1576
|
+
var FLOW_MAX_COLUMNS = 12;
|
|
1577
|
+
var FLOW_MIN_ROW_HEIGHT_MM = 3;
|
|
1578
|
+
var FLOW_MAX_ROW_HEIGHT_MM = 100;
|
|
1579
|
+
var FLOW_MIN_GAP_X_MM = 0;
|
|
1580
|
+
var FLOW_MAX_GAP_X_MM = 50;
|
|
1581
|
+
var PT_TO_MM = 25.4 / 72;
|
|
1582
|
+
function clampInt(value, min2, max2, fallback) {
|
|
1583
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
1584
|
+
return Math.min(max2, Math.max(min2, Math.round(value)));
|
|
1585
|
+
}
|
|
1586
|
+
function resolveFlowColumns(value) {
|
|
1587
|
+
return clampInt(value, FLOW_MIN_COLUMNS, FLOW_MAX_COLUMNS, 4);
|
|
1588
|
+
}
|
|
1589
|
+
function resolveFlowGapX(value) {
|
|
1590
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return 4;
|
|
1591
|
+
return Math.min(FLOW_MAX_GAP_X_MM, Math.max(FLOW_MIN_GAP_X_MM, value));
|
|
1592
|
+
}
|
|
1593
|
+
function resolveFlowRowHeight(value) {
|
|
1594
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return 8;
|
|
1595
|
+
return Math.min(FLOW_MAX_ROW_HEIGHT_MM, Math.max(FLOW_MIN_ROW_HEIGHT_MM, value));
|
|
1596
|
+
}
|
|
1597
|
+
function resolveFlowMaxSpan(value, columns) {
|
|
1598
|
+
const cols = resolveFlowColumns(columns);
|
|
1599
|
+
const fallback = Math.min(2, cols);
|
|
1600
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
1601
|
+
return Math.min(cols, Math.max(1, Math.round(value)));
|
|
1602
|
+
}
|
|
1603
|
+
function flowColumnWidthMm(width, columns, gapX) {
|
|
1604
|
+
const cols = resolveFlowColumns(columns);
|
|
1605
|
+
const gap = resolveFlowGapX(gapX);
|
|
1606
|
+
const avail = width - gap * (cols - 1);
|
|
1607
|
+
if (avail <= 0) return 0;
|
|
1608
|
+
return avail / cols;
|
|
1609
|
+
}
|
|
1610
|
+
function flowSpanWidthMm(colUnitMm, gapX, span) {
|
|
1611
|
+
const k = Math.max(1, Math.floor(span));
|
|
1612
|
+
return colUnitMm * k + gapX * (k - 1);
|
|
1613
|
+
}
|
|
1614
|
+
function estimateTextWidthMm(text, fontSizePt) {
|
|
1615
|
+
if (!text) return 0;
|
|
1616
|
+
const em = typeof fontSizePt === "number" && Number.isFinite(fontSizePt) && fontSizePt > 0 ? fontSizePt * PT_TO_MM : 12 * PT_TO_MM;
|
|
1617
|
+
let units = 0;
|
|
1618
|
+
for (const ch of text) {
|
|
1619
|
+
if (ch === " ") {
|
|
1620
|
+
units += 0.28;
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1623
|
+
const c = ch.codePointAt(0) ?? 0;
|
|
1624
|
+
if (c >= 12288 && c <= 12351 || c >= 13312 && c <= 19903 || c >= 19968 && c <= 40959 || c >= 63744 && c <= 64255 || c >= 65280 && c <= 65376 || c >= 65504 && c <= 65510 || c >= 131072) units += 1;
|
|
1625
|
+
else if (/^[0-9A-Z]$/.test(ch)) units += 0.6;
|
|
1626
|
+
else if (/^[a-z]$/.test(ch)) units += 0.5;
|
|
1627
|
+
else if (/^[\u0020-\u007f]$/.test(ch)) units += 0.4;
|
|
1628
|
+
else units += 0.75;
|
|
1629
|
+
}
|
|
1630
|
+
return units * em;
|
|
1631
|
+
}
|
|
1632
|
+
function spanForText(text, cfg) {
|
|
1633
|
+
if (!cfg.autoSpan) return 1;
|
|
1634
|
+
const ceiling = resolveFlowMaxSpan(cfg.maxSpan, cfg.columns);
|
|
1635
|
+
if (ceiling <= 1 || cfg.colUnitMm <= 0) return 1;
|
|
1636
|
+
const need = estimateTextWidthMm(text, cfg.fontSizePt);
|
|
1637
|
+
for (let k = 1; k <= ceiling; k++) {
|
|
1638
|
+
if (need <= flowSpanWidthMm(cfg.colUnitMm, cfg.gapX, k)) return k;
|
|
1639
|
+
}
|
|
1640
|
+
return ceiling;
|
|
1641
|
+
}
|
|
1642
|
+
function layoutFlowList(items, cfg) {
|
|
1643
|
+
const columns = resolveFlowColumns(cfg.columns);
|
|
1644
|
+
const gapX = resolveFlowGapX(cfg.gapX);
|
|
1645
|
+
const colUnitMm = flowColumnWidthMm(cfg.width, columns, gapX);
|
|
1646
|
+
const maxSpan = resolveFlowMaxSpan(cfg.maxSpan, columns);
|
|
1647
|
+
const rows = [];
|
|
1648
|
+
let current = [];
|
|
1649
|
+
let used = 0;
|
|
1650
|
+
for (const raw of items) {
|
|
1651
|
+
const text = String(raw ?? "");
|
|
1652
|
+
const span = spanForText(text, { ...cfg, columns, gapX, maxSpan, colUnitMm });
|
|
1653
|
+
if (current.length > 0 && used + span > columns) {
|
|
1654
|
+
rows.push({ cells: current });
|
|
1655
|
+
current = [];
|
|
1656
|
+
used = 0;
|
|
1657
|
+
}
|
|
1658
|
+
current.push({ text, span });
|
|
1659
|
+
used += span;
|
|
1660
|
+
}
|
|
1661
|
+
if (current.length > 0) rows.push({ cells: current });
|
|
1662
|
+
return rows;
|
|
1663
|
+
}
|
|
1664
|
+
function detectFlowListKey(expr, data) {
|
|
1665
|
+
if (typeof expr !== "string" || !expr.includes("{") || !data) return void 0;
|
|
1666
|
+
const roots = /* @__PURE__ */ new Set();
|
|
1667
|
+
for (const token of expr.matchAll(/\{([^{}]*)\}/g)) {
|
|
1668
|
+
for (const piece of (token[1] ?? "").split(/[^A-Za-z0-9_\u4e00-\u9fa5.]/)) {
|
|
1669
|
+
const root = piece.split(".")[0];
|
|
1670
|
+
if (root && !/^\d/.test(root)) roots.add(root);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
for (const root of roots) {
|
|
1674
|
+
if (Array.isArray(data[root])) return root;
|
|
1675
|
+
}
|
|
1676
|
+
return void 0;
|
|
1677
|
+
}
|
|
1678
|
+
var mmNum = (v) => `${Math.round(v * 1e3) / 1e3}mm`;
|
|
1679
|
+
function flowGridStyle(cfg) {
|
|
1680
|
+
const columns = resolveFlowColumns(cfg.columns);
|
|
1681
|
+
const gapX = resolveFlowGapX(cfg.gapX);
|
|
1682
|
+
const rowHeight = resolveFlowRowHeight(cfg.rowHeight);
|
|
1683
|
+
return [
|
|
1684
|
+
`display:grid`,
|
|
1685
|
+
`grid-template-columns:repeat(${columns},minmax(0,1fr))`,
|
|
1686
|
+
`column-gap:${mmNum(gapX)}`,
|
|
1687
|
+
`grid-auto-rows:minmax(${mmNum(rowHeight)},auto)`
|
|
1688
|
+
].join(";");
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1506
1691
|
// src/render/data-binder.ts
|
|
1507
1692
|
function bindData(template, printData, baseUrl, fontBaseUrl) {
|
|
1508
1693
|
const data = { ...resolveSystemVariables(), ...printData ?? {} };
|
|
@@ -1530,7 +1715,8 @@ function bindData(template, printData, baseUrl, fontBaseUrl) {
|
|
|
1530
1715
|
}
|
|
1531
1716
|
function bindElement(el, data, baseUrl) {
|
|
1532
1717
|
const cloned = { ...el, options: { ...el.options } };
|
|
1533
|
-
|
|
1718
|
+
const isFlowList = cloned.type === "flowList" || cloned.printElementType?.type === "flowList";
|
|
1719
|
+
if (!isFlowList && typeof cloned.options.formatter === "string") {
|
|
1534
1720
|
const raw = cloned.options.formatter;
|
|
1535
1721
|
if (referencesPageNumbers(raw)) {
|
|
1536
1722
|
cloned.options.rawFormatter = raw;
|
|
@@ -1552,8 +1738,23 @@ function bindElement(el, data, baseUrl) {
|
|
|
1552
1738
|
if (cloned.type === "table" || cloned.printElementType?.type === "table") {
|
|
1553
1739
|
bindTableData(cloned, data);
|
|
1554
1740
|
}
|
|
1741
|
+
if (cloned.type === "flowList" || cloned.printElementType?.type === "flowList") {
|
|
1742
|
+
bindFlowListData(cloned, data);
|
|
1743
|
+
}
|
|
1555
1744
|
return cloned;
|
|
1556
1745
|
}
|
|
1746
|
+
function bindFlowListData(el, data) {
|
|
1747
|
+
const template = typeof el.options.formatter === "string" ? el.options.formatter : "";
|
|
1748
|
+
const source = { ...el.options, dataSource: el.options.dataSource ?? detectFlowListKey(template, data) };
|
|
1749
|
+
const { list, key } = resolveListSource(source, data);
|
|
1750
|
+
const itemCtx = (item) => key ? { ...data, ...item, [key]: item } : { ...data, ...item };
|
|
1751
|
+
const items = list.map((item) => {
|
|
1752
|
+
if (!template) return String(item ?? "");
|
|
1753
|
+
return referencesPageNumbers(template) ? template : evaluateTemplate(template, itemCtx(item));
|
|
1754
|
+
});
|
|
1755
|
+
el.options._flowItems = items;
|
|
1756
|
+
el.options._flowRawFormatter = referencesPageNumbers(template) ? template : void 0;
|
|
1757
|
+
}
|
|
1557
1758
|
function resolveListSource(opts, data) {
|
|
1558
1759
|
const explicitKey = opts.dataSource ?? opts.fields?.[0]?.dataSource ?? opts.fields?.[0]?.field;
|
|
1559
1760
|
if (explicitKey && Array.isArray(data[explicitKey])) {
|
|
@@ -1629,6 +1830,12 @@ function makeRenderRow(row, resolve, keepRaw = false) {
|
|
|
1629
1830
|
barcodeType: cell.barcodeType,
|
|
1630
1831
|
qrCodeLevel: cell.qrCodeLevel,
|
|
1631
1832
|
qrQuietZone: cell.qrQuietZone,
|
|
1833
|
+
barQuietZone: cell.barQuietZone,
|
|
1834
|
+
// 条高同样必须进白名单:漏一个,属性台填的 mm 就只在设计器生效、出纸静默按缺省 30 模块
|
|
1835
|
+
barHeight: cell.barHeight,
|
|
1836
|
+
// 条宽与条码文本字号也必须在白名单里:漏一个,属性台填的倍率就只在设计器生效、出纸静默按缺省
|
|
1837
|
+
barWidth: cell.barWidth,
|
|
1838
|
+
barFontSize: cell.barFontSize,
|
|
1632
1839
|
showBarcodeText: cell.showBarcodeText,
|
|
1633
1840
|
printerDpi: cell.printerDpi,
|
|
1634
1841
|
fit: cell.fit,
|
|
@@ -1879,7 +2086,8 @@ function elementBlock() {
|
|
|
1879
2086
|
.print-table td {
|
|
1880
2087
|
border: 1px solid #ccc;
|
|
1881
2088
|
padding: 2mm 3mm;
|
|
1882
|
-
word-break:
|
|
2089
|
+
word-break: normal;
|
|
2090
|
+
overflow-wrap: break-word;
|
|
1883
2091
|
overflow: hidden;
|
|
1884
2092
|
}
|
|
1885
2093
|
.print-table thead th {
|
|
@@ -2103,6 +2311,7 @@ var SELF_BORDER_TYPES = /* @__PURE__ */ new Set(["rect", "oval", "hline", "vline
|
|
|
2103
2311
|
var VALID_STYLES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double"]);
|
|
2104
2312
|
function parseBorder(width, style, color) {
|
|
2105
2313
|
if (typeof width !== "number" || !Number.isFinite(width) || width <= 0) return null;
|
|
2314
|
+
if (style === "none") return null;
|
|
2106
2315
|
return {
|
|
2107
2316
|
borderWidth: `${width}pt`,
|
|
2108
2317
|
borderStyle: typeof style === "string" && VALID_STYLES.has(style) ? style : "solid",
|
|
@@ -3047,6 +3256,27 @@ function renderElement(el, isMeasure, containerStyle, overrideTop, ctx) {
|
|
|
3047
3256
|
return `<div class="print-element" style="${style};border:${opts.borderWidth || 1}pt ${opts.borderStyle || "solid"} ${opts.borderColor || "#333"};border-radius:50%;"${measureAttr}></div>`;
|
|
3048
3257
|
case "longText":
|
|
3049
3258
|
return `<div class="print-element" style="${style}${textStyle(opts)}${indentStyle(opts)}${elementFitStyle(fit, opts)}"${measureAttr}${fitAttr}>${esc(opts.formatter ?? opts.testData ?? "")}</div>`;
|
|
3259
|
+
case "flowList": {
|
|
3260
|
+
const columns = resolveFlowColumns(opts.flowColumns);
|
|
3261
|
+
const gapX = resolveFlowGapX(opts.flowGapX);
|
|
3262
|
+
const rowHeight = resolveFlowRowHeight(opts.flowRowHeight);
|
|
3263
|
+
const maxSpan = resolveFlowMaxSpan(opts.flowMaxSpan, columns);
|
|
3264
|
+
const boundItems = Array.isArray(opts._flowItems) ? opts._flowItems : void 0;
|
|
3265
|
+
const items = boundItems && boundItems.length > 0 ? boundItems : String(opts.testData ?? "").split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
3266
|
+
const cfg = {
|
|
3267
|
+
width,
|
|
3268
|
+
columns,
|
|
3269
|
+
gapX,
|
|
3270
|
+
rowHeight,
|
|
3271
|
+
maxSpan,
|
|
3272
|
+
fontSizePt: opts.fontSize ?? 12,
|
|
3273
|
+
autoSpan: opts.flowAutoSpan === true
|
|
3274
|
+
};
|
|
3275
|
+
const cells = layoutFlowList(items, cfg).flatMap((row) => row.cells).map((c) => `<div class="print-flow-cell"${c.span > 1 ? ` style="grid-column:span ${c.span};"` : ""}>${esc(c.text)}</div>`).join("\n ");
|
|
3276
|
+
return `<div class="print-element" style="${style}${textStyle(opts)}overflow:hidden;${flowGridStyle(cfg)};"${measureAttr}${fitAttr}>
|
|
3277
|
+
${cells}
|
|
3278
|
+
</div>`;
|
|
3279
|
+
}
|
|
3050
3280
|
case "html":
|
|
3051
3281
|
return `<div class="print-element" style="${style}"${measureAttr}>${opts.testData ?? opts.title ?? ""}</div>`;
|
|
3052
3282
|
default:
|
|
@@ -3063,9 +3293,13 @@ function codeImgHtml(value, cellType, opts, io) {
|
|
|
3063
3293
|
qrCodeLevel: opts.qrCodeLevel != null ? String(opts.qrCodeLevel) : void 0,
|
|
3064
3294
|
// 0 是合法档(无白边),必须用 typeof 判定而非 or/?? 之类假值判断
|
|
3065
3295
|
qrQuietZone: typeof opts.qrQuietZone === "number" ? opts.qrQuietZone : void 0,
|
|
3296
|
+
barQuietZone: typeof opts.barQuietZone === "number" ? opts.barQuietZone : void 0,
|
|
3297
|
+
// 条高(mm):元素台与单元格台都写 barHeight,非法/未填交由布局函数回退缺省档
|
|
3298
|
+
barHeightMm: typeof opts.barHeight === "number" ? opts.barHeight : void 0,
|
|
3066
3299
|
showText: opts.hideTitle !== void 0 ? !opts.hideTitle : opts.showBarcodeText,
|
|
3067
3300
|
barWidth: typeof opts.barWidth === "number" ? opts.barWidth : void 0,
|
|
3068
|
-
|
|
3301
|
+
// 元素台的条码文本字号是 fontSize;单元格台的文本字号是 barFontSize(单元格的 fontSize 是正文字号,不该拿来决定条码)
|
|
3302
|
+
fontSize: typeof (opts.barFontSize ?? opts.fontSize) === "number" ? opts.barFontSize ?? opts.fontSize : void 0,
|
|
3069
3303
|
printerDpi: isBarcode ? io.printerDpi : void 0,
|
|
3070
3304
|
targetWidthMm: isBarcode ? barcodeAvailableBoxMm(io.targetWidthMm, maxWidth) : void 0,
|
|
3071
3305
|
targetHeightMm: isBarcode ? barcodeAvailableBoxMm(io.targetHeightMm, maxHeight) : void 0
|
|
@@ -3096,8 +3330,9 @@ function matrixCellStyle(cell, opts) {
|
|
|
3096
3330
|
const fontSize = cell.fittedFontSize ?? cell.fontSize ?? opts.tableDefaultFontSize;
|
|
3097
3331
|
const color = cell.color ?? opts.tableDefaultColor;
|
|
3098
3332
|
const padding = cell.padding ?? opts.tableDefaultPadding ?? 1;
|
|
3333
|
+
const fontFamily = cell.fontFamily ?? opts.tableDefaultFontFamily;
|
|
3099
3334
|
if (fontSize) parts.push(`font-size:${fontSize}pt`);
|
|
3100
|
-
if (
|
|
3335
|
+
if (fontFamily) parts.push(`font-family:${escapeInlineStyleValue(toFontFamilyStack(fontFamily))}`);
|
|
3101
3336
|
if (cell.fontWeight) parts.push(`font-weight:${cell.fontWeight}`);
|
|
3102
3337
|
if (color) parts.push(`color:${color}`);
|
|
3103
3338
|
if (cell.backgroundColor) parts.push(`background-color:${cell.backgroundColor}`);
|
|
@@ -3105,7 +3340,7 @@ function matrixCellStyle(cell, opts) {
|
|
|
3105
3340
|
if (cell.align === "justify") parts.push("text-align-last:justify");
|
|
3106
3341
|
parts.push(`vertical-align:${cell.valign ?? "middle"}`);
|
|
3107
3342
|
parts.push(`padding:${padding}mm`);
|
|
3108
|
-
parts.push(cell.wordWrap === false ? "white-space:nowrap;overflow:hidden" : "word-break:break-
|
|
3343
|
+
parts.push(cell.wordWrap === false ? "white-space:nowrap;overflow:hidden" : "white-space:pre-wrap;word-break:normal;overflow-wrap:break-word");
|
|
3109
3344
|
const b = cell.borders ?? {};
|
|
3110
3345
|
for (const side of ["top", "right", "bottom", "left"]) {
|
|
3111
3346
|
const border = b[side];
|
|
@@ -3335,7 +3570,9 @@ function codeSpecKey(value, cellType, opts = {}) {
|
|
|
3335
3570
|
opts.showText ?? null,
|
|
3336
3571
|
opts.barWidth ?? null,
|
|
3337
3572
|
opts.fontSize ?? null,
|
|
3338
|
-
opts.qrQuietZone ?? null
|
|
3573
|
+
opts.qrQuietZone ?? null,
|
|
3574
|
+
opts.barQuietZone ?? null,
|
|
3575
|
+
opts.barHeightMm ?? null
|
|
3339
3576
|
]);
|
|
3340
3577
|
}
|
|
3341
3578
|
function createMapCodeRenderer(map) {
|
package/dist/browser/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @worm-vue3-print/core v1.3.
|
|
2
|
+
* @worm-vue3-print/core v1.3.10
|
|
3
3
|
* Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
|
|
4
4
|
* SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
6
6
|
*/
|
|
7
|
-
import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-
|
|
8
|
-
import { P as PrintRuntime, F as FitFontSize } from '../ports-
|
|
7
|
+
import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-DW3mxuRF.cjs';
|
|
8
|
+
import { P as PrintRuntime, F as FitFontSize } from '../ports-DJ7_blE7.cjs';
|
|
9
9
|
|
|
10
10
|
interface BrowserRenderResult {
|
|
11
11
|
/** 最终多页 HTML 字符串 */
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @worm-vue3-print/core v1.3.
|
|
2
|
+
* @worm-vue3-print/core v1.3.10
|
|
3
3
|
* Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
|
|
4
4
|
* SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
6
6
|
*/
|
|
7
|
-
import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-
|
|
8
|
-
import { P as PrintRuntime, F as FitFontSize } from '../ports-
|
|
7
|
+
import { P as PageLayout, T as TemplateData, M as MultiPageTemplateData, C as CodeRenderer, D as DriverFactory, R as RawMeasurement, a as CodeSpec } from '../driver-DW3mxuRF.js';
|
|
8
|
+
import { P as PrintRuntime, F as FitFontSize } from '../ports-Brn5xcLD.js';
|
|
9
9
|
|
|
10
10
|
interface BrowserRenderResult {
|
|
11
11
|
/** 最终多页 HTML 字符串 */
|
package/dist/browser/index.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @worm-vue3-print/core v1.3.
|
|
2
|
+
* @worm-vue3-print/core v1.3.10
|
|
3
3
|
* Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
|
|
4
4
|
* SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
6
6
|
*/
|
|
7
7
|
import {
|
|
8
|
-
BARCODE_BAR_HEIGHT_MODULES,
|
|
9
8
|
BARCODE_MARGIN_BOTTOM_MODULES,
|
|
10
|
-
BARCODE_QUIET_ZONE_MODULES,
|
|
11
9
|
BARCODE_TEXT_FONT_SIZE_MODULES,
|
|
12
10
|
EXECUTOR_TARGETS,
|
|
11
|
+
QR_DEFAULT_QUIET_MODULES,
|
|
12
|
+
barcodeQuietZoneModules,
|
|
13
13
|
barcodeUnitsPerModule,
|
|
14
14
|
createDomHostRuntime,
|
|
15
15
|
floorFontSize,
|
|
16
|
+
layoutBarcodeSize,
|
|
16
17
|
mmToPx,
|
|
17
18
|
prepareDocument,
|
|
18
|
-
resolveBarcodeSize,
|
|
19
19
|
resolveShrinkMinFontSize
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-7FXIWNYK.js";
|
|
21
21
|
|
|
22
22
|
// src/browser/browser-code-renderer.ts
|
|
23
23
|
import JsBarcode from "jsbarcode";
|
|
@@ -33,36 +33,39 @@ function readViewBox(svg) {
|
|
|
33
33
|
function renderBarcodeSvg(value, opts) {
|
|
34
34
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
35
35
|
const unitPerModule = barcodeUnitsPerModule(opts.barWidth);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (viewBox) {
|
|
51
|
-
const size = resolveBarcodeSize({
|
|
52
|
-
unitWidth: viewBox.width / unitPerModule,
|
|
53
|
-
unitHeight: viewBox.height / unitPerModule,
|
|
54
|
-
boxWidthMm: opts.targetWidthMm ?? 0,
|
|
55
|
-
boxHeightMm: opts.targetHeightMm ?? 0,
|
|
56
|
-
dpi: opts.printerDpi,
|
|
57
|
-
barWidth: opts.barWidth
|
|
36
|
+
const quietModules = barcodeQuietZoneModules(opts.barQuietZone);
|
|
37
|
+
const measure = (barHeightModules) => {
|
|
38
|
+
JsBarcode(svg, value, {
|
|
39
|
+
format: opts.barcodeType || "CODE128",
|
|
40
|
+
width: unitPerModule,
|
|
41
|
+
height: barHeightModules * unitPerModule,
|
|
42
|
+
displayValue: opts.showText !== false,
|
|
43
|
+
fontSize: (opts.fontSize ?? BARCODE_TEXT_FONT_SIZE_MODULES) * unitPerModule,
|
|
44
|
+
// 静区只留左右:上下留白会白白吃掉元素高度(jsbarcode 的 margin 是四边通配)
|
|
45
|
+
margin: 0,
|
|
46
|
+
marginLeft: quietModules * unitPerModule,
|
|
47
|
+
marginRight: quietModules * unitPerModule,
|
|
48
|
+
marginTop: 0,
|
|
49
|
+
marginBottom: BARCODE_MARGIN_BOTTOM_MODULES * unitPerModule
|
|
58
50
|
});
|
|
59
|
-
svg
|
|
60
|
-
|
|
51
|
+
const viewBox = readViewBox(svg);
|
|
52
|
+
return viewBox ? { widthUnits: viewBox.width, heightUnits: viewBox.height } : null;
|
|
53
|
+
};
|
|
54
|
+
const layout = layoutBarcodeSize({
|
|
55
|
+
barHeightMm: opts.barHeightMm,
|
|
56
|
+
boxWidthMm: opts.targetWidthMm ?? 0,
|
|
57
|
+
boxHeightMm: opts.targetHeightMm ?? 0,
|
|
58
|
+
dpi: opts.printerDpi,
|
|
59
|
+
barWidth: opts.barWidth,
|
|
60
|
+
measure
|
|
61
|
+
});
|
|
62
|
+
if (layout.size) {
|
|
63
|
+
svg.setAttribute("width", `${layout.size.widthMm}mm`);
|
|
64
|
+
svg.setAttribute("height", `${layout.size.heightMm}mm`);
|
|
61
65
|
}
|
|
62
66
|
svg.setAttribute("shape-rendering", "crispEdges");
|
|
63
67
|
return svg.outerHTML;
|
|
64
68
|
}
|
|
65
|
-
var QR_DEFAULT_QUIET_MODULES = 0;
|
|
66
69
|
function qrQuietModules(value) {
|
|
67
70
|
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : QR_DEFAULT_QUIET_MODULES;
|
|
68
71
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @worm-vue3-print/core v1.3.
|
|
2
|
+
* @worm-vue3-print/core v1.3.10
|
|
3
3
|
* Copyright (c) 2026 worm <liu_long_qqcom@qq.com>
|
|
4
4
|
* SPDX-FileCopyrightText: 2026 worm <liu_long_qqcom@qq.com>
|
|
5
5
|
* SPDX-License-Identifier: MIT
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
evaluate,
|
|
10
10
|
parse,
|
|
11
11
|
tokenize
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-7FXIWNYK.js";
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
15
|
var TemplateEngine = class {
|