@asteby/storefront-react 0.26.1 → 0.28.1
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/README.md +7 -2
- package/dist/account-server.cjs +533 -83
- package/dist/account-server.cjs.map +1 -1
- package/dist/account-server.d.cts +13 -2
- package/dist/account-server.d.ts +13 -2
- package/dist/account-server.js +23 -6
- package/dist/account-server.js.map +1 -1
- package/dist/account.cjs +572 -96
- package/dist/account.cjs.map +1 -1
- package/dist/account.d.cts +82 -45
- package/dist/account.d.ts +82 -45
- package/dist/account.js +53 -14
- package/dist/account.js.map +1 -1
- package/dist/checkout.cjs +114 -38
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +24 -1
- package/dist/checkout.d.ts +24 -1
- package/dist/checkout.js +114 -38
- package/dist/checkout.js.map +1 -1
- package/dist/{chunk-MNLROALF.js → chunk-4DZW3R33.js} +19 -2
- package/dist/chunk-4DZW3R33.js.map +1 -0
- package/dist/chunk-BXKV2KWZ.js +291 -0
- package/dist/chunk-BXKV2KWZ.js.map +1 -0
- package/dist/chunk-LIUEQENV.js +156 -0
- package/dist/chunk-LIUEQENV.js.map +1 -0
- package/dist/payments-server.cjs +17 -0
- package/dist/payments-server.cjs.map +1 -1
- package/dist/payments-server.js +2 -2
- package/dist/payments.cjs +17 -0
- package/dist/payments.cjs.map +1 -1
- package/dist/payments.js +2 -2
- package/dist/voucher-document-FWH4DQ5N.js +72 -0
- package/dist/voucher-document-FWH4DQ5N.js.map +1 -0
- package/dist/voucher-pdf-LQC333AB.js +213 -0
- package/dist/voucher-pdf-LQC333AB.js.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-MNLROALF.js.map +0 -1
- package/dist/chunk-TXEYBDFG.js +0 -182
- package/dist/chunk-TXEYBDFG.js.map +0 -1
- package/dist/voucher-document-SFWJCLTN.js +0 -124
- package/dist/voucher-document-SFWJCLTN.js.map +0 -1
package/dist/chunk-TXEYBDFG.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
// src/account/voucher.ts
|
|
2
|
-
var MAX = 256;
|
|
3
|
-
function text(v) {
|
|
4
|
-
if (typeof v === "number" && Number.isFinite(v)) return String(v);
|
|
5
|
-
if (typeof v !== "string") return null;
|
|
6
|
-
const s = v.trim().slice(0, MAX);
|
|
7
|
-
return s || null;
|
|
8
|
-
}
|
|
9
|
-
function moneyOf(v) {
|
|
10
|
-
if (!v || typeof v !== "object") return null;
|
|
11
|
-
const m = v;
|
|
12
|
-
const amount = text(m.amount);
|
|
13
|
-
const cur = text(m.currency_code);
|
|
14
|
-
return amount && cur && Number.isFinite(Number(amount)) ? { amount, currency_code: cur.toUpperCase() } : null;
|
|
15
|
-
}
|
|
16
|
-
function voucherOf(p) {
|
|
17
|
-
const pay = p?.payment;
|
|
18
|
-
if (!pay || typeof pay !== "object") return null;
|
|
19
|
-
const v = {
|
|
20
|
-
method: text(pay.method ?? pay.provider),
|
|
21
|
-
reference: text(pay.reference),
|
|
22
|
-
barcode: text(pay.barcode),
|
|
23
|
-
clabe: text(pay.clabe),
|
|
24
|
-
expires_at: text(pay.expires_at) ?? text(p?.expires_at),
|
|
25
|
-
amount: moneyOf(pay.amount) ?? moneyOf(p?.total),
|
|
26
|
-
instructions: text(pay.instructions)
|
|
27
|
-
};
|
|
28
|
-
return v.reference || v.barcode || v.clabe ? v : null;
|
|
29
|
-
}
|
|
30
|
-
function barcodeValue(v) {
|
|
31
|
-
return v.barcode ?? (v.method?.toLowerCase() === "oxxo" ? v.reference : null);
|
|
32
|
-
}
|
|
33
|
-
var BARS = [
|
|
34
|
-
"11011001100",
|
|
35
|
-
"11001101100",
|
|
36
|
-
"11001100110",
|
|
37
|
-
"10010011000",
|
|
38
|
-
"10010001100",
|
|
39
|
-
"10001001100",
|
|
40
|
-
"10011001000",
|
|
41
|
-
"10011000100",
|
|
42
|
-
"10001100100",
|
|
43
|
-
"11001001000",
|
|
44
|
-
"11001000100",
|
|
45
|
-
"11000100100",
|
|
46
|
-
"10110011100",
|
|
47
|
-
"10011011100",
|
|
48
|
-
"10011001110",
|
|
49
|
-
"10111001100",
|
|
50
|
-
"10011101100",
|
|
51
|
-
"10011100110",
|
|
52
|
-
"11001110010",
|
|
53
|
-
"11001011100",
|
|
54
|
-
"11001001110",
|
|
55
|
-
"11011100100",
|
|
56
|
-
"11001110100",
|
|
57
|
-
"11101101110",
|
|
58
|
-
"11101001100",
|
|
59
|
-
"11100101100",
|
|
60
|
-
"11100100110",
|
|
61
|
-
"11101100100",
|
|
62
|
-
"11100110100",
|
|
63
|
-
"11100110010",
|
|
64
|
-
"11011011000",
|
|
65
|
-
"11011000110",
|
|
66
|
-
"11000110110",
|
|
67
|
-
"10100011000",
|
|
68
|
-
"10001011000",
|
|
69
|
-
"10001000110",
|
|
70
|
-
"10110001000",
|
|
71
|
-
"10001101000",
|
|
72
|
-
"10001100010",
|
|
73
|
-
"11010001000",
|
|
74
|
-
"11000101000",
|
|
75
|
-
"11000100010",
|
|
76
|
-
"10110111000",
|
|
77
|
-
"10110001110",
|
|
78
|
-
"10001101110",
|
|
79
|
-
"10111011000",
|
|
80
|
-
"10111000110",
|
|
81
|
-
"10001110110",
|
|
82
|
-
"11101110110",
|
|
83
|
-
"11010001110",
|
|
84
|
-
"11000101110",
|
|
85
|
-
"11011101000",
|
|
86
|
-
"11011100010",
|
|
87
|
-
"11011101110",
|
|
88
|
-
"11101011000",
|
|
89
|
-
"11101000110",
|
|
90
|
-
"11100010110",
|
|
91
|
-
"11101101000",
|
|
92
|
-
"11101100010",
|
|
93
|
-
"11100011010",
|
|
94
|
-
"11101111010",
|
|
95
|
-
"11001000010",
|
|
96
|
-
"11110001010",
|
|
97
|
-
"10100110000",
|
|
98
|
-
"10100001100",
|
|
99
|
-
"10010110000",
|
|
100
|
-
"10010000110",
|
|
101
|
-
"10000101100",
|
|
102
|
-
"10000100110",
|
|
103
|
-
"10110010000",
|
|
104
|
-
"10110000100",
|
|
105
|
-
"10011010000",
|
|
106
|
-
"10011000010",
|
|
107
|
-
"10000110100",
|
|
108
|
-
"10000110010",
|
|
109
|
-
"11000010010",
|
|
110
|
-
"11001010000",
|
|
111
|
-
"11110111010",
|
|
112
|
-
"11000010100",
|
|
113
|
-
"10001111010",
|
|
114
|
-
"10100111100",
|
|
115
|
-
"10010111100",
|
|
116
|
-
"10010011110",
|
|
117
|
-
"10111100100",
|
|
118
|
-
"10011110100",
|
|
119
|
-
"10011110010",
|
|
120
|
-
"11110100100",
|
|
121
|
-
"11110010100",
|
|
122
|
-
"11110010010",
|
|
123
|
-
"11011011110",
|
|
124
|
-
"11011110110",
|
|
125
|
-
"11110110110",
|
|
126
|
-
"10101111000",
|
|
127
|
-
"10100011110",
|
|
128
|
-
"10001011110",
|
|
129
|
-
"10111101000",
|
|
130
|
-
"10111100010",
|
|
131
|
-
"11110101000",
|
|
132
|
-
"11110100010",
|
|
133
|
-
"10111011110",
|
|
134
|
-
"10111101110",
|
|
135
|
-
"11101011110",
|
|
136
|
-
"11110101110",
|
|
137
|
-
"11010000100",
|
|
138
|
-
"11010010000",
|
|
139
|
-
"11010011100"
|
|
140
|
-
];
|
|
141
|
-
var STOP = "1100011101011";
|
|
142
|
-
function code128Modules(value) {
|
|
143
|
-
if (!value || value.length > 80) return null;
|
|
144
|
-
let codes;
|
|
145
|
-
if (/^\d+$/.test(value) && value.length % 2 === 0) {
|
|
146
|
-
codes = [105];
|
|
147
|
-
for (let i = 0; i < value.length; i += 2) codes.push(Number(value.slice(i, i + 2)));
|
|
148
|
-
} else {
|
|
149
|
-
codes = [104];
|
|
150
|
-
for (const ch of value) {
|
|
151
|
-
const c = ch.charCodeAt(0);
|
|
152
|
-
if (c < 32 || c > 126) return null;
|
|
153
|
-
codes.push(c - 32);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
let sum = codes[0];
|
|
157
|
-
for (let i = 1; i < codes.length; i++) sum += codes[i] * i;
|
|
158
|
-
codes.push(sum % 103);
|
|
159
|
-
return codes.map((c) => BARS[c]).join("") + STOP;
|
|
160
|
-
}
|
|
161
|
-
function barcodeGeometry(value, opts = {}) {
|
|
162
|
-
const bits = code128Modules(value);
|
|
163
|
-
if (!bits) return null;
|
|
164
|
-
const mod = opts.module ?? 2;
|
|
165
|
-
const quiet = 10;
|
|
166
|
-
const rects = [];
|
|
167
|
-
for (let i = 0; i < bits.length; ) {
|
|
168
|
-
if (bits[i] === "0") {
|
|
169
|
-
i++;
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
let j = i;
|
|
173
|
-
while (j < bits.length && bits[j] === "1") j++;
|
|
174
|
-
rects.push({ x: (quiet + i) * mod, w: (j - i) * mod });
|
|
175
|
-
i = j;
|
|
176
|
-
}
|
|
177
|
-
return { width: (bits.length + quiet * 2) * mod, height: opts.height ?? 70, rects };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export { barcodeGeometry, barcodeValue, code128Modules, voucherOf };
|
|
181
|
-
//# sourceMappingURL=chunk-TXEYBDFG.js.map
|
|
182
|
-
//# sourceMappingURL=chunk-TXEYBDFG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/account/voucher.ts"],"names":[],"mappings":";AAkBA,IAAM,GAAA,GAAM,GAAA;AAEZ,SAAS,KAAK,CAAA,EAA2B;AACvC,EAAA,IAAI,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,SAAS,CAAC,CAAA,EAAG,OAAO,MAAA,CAAO,CAAC,CAAA;AAChE,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,IAAA;AAClC,EAAA,MAAM,IAAI,CAAA,CAAE,IAAA,EAAK,CAAE,KAAA,CAAM,GAAG,GAAG,CAAA;AAC/B,EAAA,OAAO,CAAA,IAAK,IAAA;AACd;AAEA,SAAS,QAAQ,CAAA,EAA0B;AACzC,EAAA,IAAI,CAAC,CAAA,IAAK,OAAO,CAAA,KAAM,UAAU,OAAO,IAAA;AACxC,EAAA,MAAM,CAAA,GAAI,CAAA;AACV,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,CAAA,CAAE,MAAM,CAAA;AAC5B,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,CAAA,CAAE,aAAa,CAAA;AAChC,EAAA,OAAO,MAAA,IAAU,GAAA,IAAO,MAAA,CAAO,QAAA,CAAS,OAAO,MAAM,CAAC,CAAA,GAAI,EAAE,MAAA,EAAQ,aAAA,EAAe,GAAA,CAAI,WAAA,IAAc,GAAI,IAAA;AAC3G;AAGO,SAAS,UAAU,CAAA,EAAoG;AAC5H,EAAA,MAAM,MAAM,CAAA,EAAG,OAAA;AACf,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,IAAA;AAC5C,EAAA,MAAM,CAAA,GAAiB;AAAA,IACrB,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,MAAA,IAAU,IAAI,QAAQ,CAAA;AAAA,IACvC,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA;AAAA,IAC7B,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AAAA,IACzB,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAAA,IACrB,YAAY,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,IAAK,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA,IACtD,QAAQ,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IAAK,OAAA,CAAQ,GAAG,KAAK,CAAA;AAAA,IAC/C,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,YAAY;AAAA,GACrC;AACA,EAAA,OAAO,EAAE,SAAA,IAAa,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,QAAQ,CAAA,GAAI,IAAA;AACnD;AAGO,SAAS,aAAa,CAAA,EAAyE;AACpG,EAAA,OAAO,CAAA,CAAE,YAAY,CAAA,CAAE,MAAA,EAAQ,aAAY,KAAM,MAAA,GAAS,EAAE,SAAA,GAAY,IAAA,CAAA;AAC1E;AAGA,IAAM,IAAA,GAAO;AAAA,EACX,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EACvI,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe;AAC7E,CAAA;AACA,IAAM,IAAA,GAAO,eAAA;AAMN,SAAS,eAAe,KAAA,EAA8B;AAC3D,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,GAAS,IAAI,OAAO,IAAA;AACxC,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,QAAQ,IAAA,CAAK,KAAK,KAAK,KAAA,CAAM,MAAA,GAAS,MAAM,CAAA,EAAG;AACjD,IAAA,KAAA,GAAQ,CAAC,GAAG,CAAA;AACZ,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,KAAK,CAAA,EAAG,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,MAAM,KAAA,CAAM,CAAA,EAAG,CAAA,GAAI,CAAC,CAAC,CAAC,CAAA;AAAA,EACpF,CAAA,MAAO;AACL,IAAA,KAAA,GAAQ,CAAC,GAAG,CAAA;AACZ,IAAA,KAAA,MAAW,MAAM,KAAA,EAAO;AACtB,MAAA,MAAM,CAAA,GAAI,EAAA,CAAG,UAAA,CAAW,CAAC,CAAA;AACzB,MAAA,IAAI,CAAA,GAAI,EAAA,IAAM,CAAA,GAAI,GAAA,EAAK,OAAO,IAAA;AAC9B,MAAA,KAAA,CAAM,IAAA,CAAK,IAAI,EAAE,CAAA;AAAA,IACnB;AAAA,EACF;AACA,EAAA,IAAI,GAAA,GAAM,MAAM,CAAC,CAAA;AACjB,EAAA,KAAA,IAAS,CAAA,GAAI,GAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK,GAAA,IAAO,KAAA,CAAM,CAAC,CAAA,GAAK,CAAA;AAC1D,EAAA,KAAA,CAAM,IAAA,CAAK,MAAM,GAAG,CAAA;AACpB,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA,GAAI,IAAA;AAC9C;AAKO,SAAS,eAAA,CAAgB,KAAA,EAAe,IAAA,GAA6C,EAAC,EAA2B;AACtH,EAAA,MAAM,IAAA,GAAO,eAAe,KAAK,CAAA;AACjC,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,MAAM,GAAA,GAAM,KAAK,MAAA,IAAU,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQ,EAAA;AACd,EAAA,MAAM,QAAoC,EAAC;AAC3C,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,IAAU;AACjC,IAAA,IAAI,IAAA,CAAK,CAAC,CAAA,KAAM,GAAA,EAAK;AACnB,MAAA,CAAA,EAAA;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,OAAO,IAAI,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,CAAC,MAAM,GAAA,EAAK,CAAA,EAAA;AAC3C,IAAA,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,EAAA,CAAI,KAAA,GAAQ,CAAA,IAAK,KAAK,CAAA,EAAA,CAAI,CAAA,GAAI,CAAA,IAAK,GAAA,EAAK,CAAA;AACrD,IAAA,CAAA,GAAI,CAAA;AAAA,EACN;AACA,EAAA,OAAO,EAAE,KAAA,EAAA,CAAQ,IAAA,CAAK,MAAA,GAAS,KAAA,GAAQ,CAAA,IAAK,GAAA,EAAK,MAAA,EAAQ,IAAA,CAAK,MAAA,IAAU,EAAA,EAAI,KAAA,EAAM;AACpF","file":"chunk-TXEYBDFG.js","sourcesContent":["/**\n * Pure pieces of the cash voucher (OXXO, SPEI, deposit): the normalized `VoucherView` of a `PendingPayment` and the\n * Code 128 barcode (the one cashiers' readers scan). No React, no DOM: the same code draws the barcode in the page\n * (`<Barcode>`) and in the printable document (`voucher-document.ts`, loaded only when the buyer prints).\n */\nimport type { Money, PendingPayment } from '@asteby/storefront'\n\nexport type VoucherView = {\n /** `oxxo`, `spei`, ... as the gateway publishes it. */\n method: string | null\n reference: string | null\n barcode: string | null\n clabe: string | null\n expires_at: string | null\n amount: Money | null\n instructions: string | null\n}\n\nconst MAX = 256\n\nfunction text(v: unknown): string | null {\n if (typeof v === 'number' && Number.isFinite(v)) return String(v)\n if (typeof v !== 'string') return null\n const s = v.trim().slice(0, MAX)\n return s || null\n}\n\nfunction moneyOf(v: unknown): Money | null {\n if (!v || typeof v !== 'object') return null\n const m = v as Record<string, unknown>\n const amount = text(m.amount)\n const cur = text(m.currency_code)\n return amount && cur && Number.isFinite(Number(amount)) ? { amount, currency_code: cur.toUpperCase() } : null\n}\n\n/** The voucher of a pending payment; `null` when it has neither reference, barcode nor CLABE (nothing to pay with). */\nexport function voucherOf(p: Pick<PendingPayment, 'payment' | 'total' | 'expires_at'> | null | undefined): VoucherView | null {\n const pay = p?.payment\n if (!pay || typeof pay !== 'object') return null\n const v: VoucherView = {\n method: text(pay.method ?? pay.provider),\n reference: text(pay.reference),\n barcode: text(pay.barcode),\n clabe: text(pay.clabe),\n expires_at: text(pay.expires_at) ?? text(p?.expires_at),\n amount: moneyOf(pay.amount) ?? moneyOf(p?.total),\n instructions: text(pay.instructions),\n }\n return v.reference || v.barcode || v.clabe ? v : null\n}\n\n/** The value the barcode encodes: the gateway's `barcode`, else the reference of an OXXO voucher. */\nexport function barcodeValue(v: Pick<VoucherView, 'barcode' | 'method' | 'reference'>): string | null {\n return v.barcode ?? (v.method?.toLowerCase() === 'oxxo' ? v.reference : null)\n}\n\n// 11-module patterns of symbols 0..105 and the 13-module stop (ISO/IEC 15417).\nconst BARS = [\n '11011001100', '11001101100', '11001100110', '10010011000', '10010001100', '10001001100', '10011001000', '10011000100', '10001100100', '11001001000',\n '11001000100', '11000100100', '10110011100', '10011011100', '10011001110', '10111001100', '10011101100', '10011100110', '11001110010', '11001011100',\n '11001001110', '11011100100', '11001110100', '11101101110', '11101001100', '11100101100', '11100100110', '11101100100', '11100110100', '11100110010',\n '11011011000', '11011000110', '11000110110', '10100011000', '10001011000', '10001000110', '10110001000', '10001101000', '10001100010', '11010001000',\n '11000101000', '11000100010', '10110111000', '10110001110', '10001101110', '10111011000', '10111000110', '10001110110', '11101110110', '11010001110',\n '11000101110', '11011101000', '11011100010', '11011101110', '11101011000', '11101000110', '11100010110', '11101101000', '11101100010', '11100011010',\n '11101111010', '11001000010', '11110001010', '10100110000', '10100001100', '10010110000', '10010000110', '10000101100', '10000100110', '10110010000',\n '10110000100', '10011010000', '10011000010', '10000110100', '10000110010', '11000010010', '11001010000', '11110111010', '11000010100', '10001111010',\n '10100111100', '10010111100', '10010011110', '10111100100', '10011110100', '10011110010', '11110100100', '11110010100', '11110010010', '11011011110',\n '11011110110', '11110110110', '10101111000', '10100011110', '10001011110', '10111101000', '10111100010', '11110101000', '11110100010', '10111011110',\n '10111101110', '11101011110', '11110101110', '11010000100', '11010010000', '11010011100',\n]\nconst STOP = '1100011101011'\n\n/**\n * Modules (`1` bar, `0` space) of the Code 128 of `value`: set C (digit pairs) when it is all digits of even length,\n * set B (printable ASCII) otherwise. `null` when it cannot be encoded.\n */\nexport function code128Modules(value: string): string | null {\n if (!value || value.length > 80) return null\n let codes: number[]\n if (/^\\d+$/.test(value) && value.length % 2 === 0) {\n codes = [105]\n for (let i = 0; i < value.length; i += 2) codes.push(Number(value.slice(i, i + 2)))\n } else {\n codes = [104]\n for (const ch of value) {\n const c = ch.charCodeAt(0)\n if (c < 32 || c > 126) return null\n codes.push(c - 32)\n }\n }\n let sum = codes[0]!\n for (let i = 1; i < codes.length; i++) sum += codes[i]! * i\n codes.push(sum % 103)\n return codes.map((c) => BARS[c]).join('') + STOP\n}\n\nexport type BarcodeGeometry = { width: number; height: number; rects: { x: number; w: number }[] }\n\n/** Bars of the barcode as rectangles (quiet zone of 10 modules each side included in `width`). `null` if not encodable. */\nexport function barcodeGeometry(value: string, opts: { module?: number; height?: number } = {}): BarcodeGeometry | null {\n const bits = code128Modules(value)\n if (!bits) return null\n const mod = opts.module ?? 2\n const quiet = 10\n const rects: { x: number; w: number }[] = []\n for (let i = 0; i < bits.length; ) {\n if (bits[i] === '0') {\n i++\n continue\n }\n let j = i\n while (j < bits.length && bits[j] === '1') j++\n rects.push({ x: (quiet + i) * mod, w: (j - i) * mod })\n i = j\n }\n return { width: (bits.length + quiet * 2) * mod, height: opts.height ?? 70, rects }\n}\n"]}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { barcodeValue, barcodeGeometry } from './chunk-TXEYBDFG.js';
|
|
2
|
-
|
|
3
|
-
// src/account/voucher-document.ts
|
|
4
|
-
function esc(s) {
|
|
5
|
-
return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
6
|
-
}
|
|
7
|
-
var ES = {
|
|
8
|
-
title: "Ficha de pago",
|
|
9
|
-
total: "Total a pagar",
|
|
10
|
-
reference: "Referencia",
|
|
11
|
-
clabe: "CLABE",
|
|
12
|
-
expires: "Vence",
|
|
13
|
-
expiresNote: "Pasada esa fecha la ficha deja de ser v\xE1lida.",
|
|
14
|
-
order: "Pedido",
|
|
15
|
-
barcode: "C\xF3digo de barras",
|
|
16
|
-
print: "Imprimir ficha",
|
|
17
|
-
footer: "Tu pedido se genera cuando se confirma el pago. Esta ficha es de un solo uso; no la compartas.",
|
|
18
|
-
stepsCash: [
|
|
19
|
-
"Acude a la tienda OXXO (o el comercio indicado) y di que vas a hacer un pago de servicio en efectivo.",
|
|
20
|
-
"Muestra el c\xF3digo de barras o dicta la referencia y paga el monto exacto.",
|
|
21
|
-
"Conserva tu comprobante: confirmaremos tu pago autom\xE1ticamente."
|
|
22
|
-
],
|
|
23
|
-
stepsSpei: ["Entra a la banca en l\xEDnea o app de tu banco.", "Haz una transferencia SPEI a la CLABE indicada por el monto exacto.", "Conserva tu comprobante: confirmaremos tu pago autom\xE1ticamente."],
|
|
24
|
-
methods: { oxxo: "OXXO", spei: "Transferencia SPEI", bank_transfer: "Transferencia bancaria", bank_deposit: "Dep\xF3sito bancario", cash: "Pago en efectivo" },
|
|
25
|
-
cash: "Pago en efectivo"
|
|
26
|
-
};
|
|
27
|
-
var EN = {
|
|
28
|
-
title: "Payment voucher",
|
|
29
|
-
total: "Amount to pay",
|
|
30
|
-
reference: "Reference",
|
|
31
|
-
clabe: "CLABE",
|
|
32
|
-
expires: "Expires",
|
|
33
|
-
expiresNote: "After that date the voucher is no longer valid.",
|
|
34
|
-
order: "Order",
|
|
35
|
-
barcode: "Barcode",
|
|
36
|
-
print: "Print voucher",
|
|
37
|
-
footer: "Your order is created when the payment is confirmed. This voucher is single-use; do not share it.",
|
|
38
|
-
stepsCash: [
|
|
39
|
-
"Go to an OXXO store (or the store indicated) and say you want to make a cash service payment.",
|
|
40
|
-
"Show the barcode or read out the reference and pay the exact amount.",
|
|
41
|
-
"Keep your receipt: we will confirm your payment automatically."
|
|
42
|
-
],
|
|
43
|
-
stepsSpei: ["Open your bank online or app.", "Make a SPEI transfer to the CLABE below for the exact amount.", "Keep your receipt: we will confirm your payment automatically."],
|
|
44
|
-
methods: { oxxo: "OXXO", spei: "SPEI transfer", bank_transfer: "Bank transfer", bank_deposit: "Bank deposit", cash: "Cash payment" },
|
|
45
|
-
cash: "Cash payment"
|
|
46
|
-
};
|
|
47
|
-
var CSS = `
|
|
48
|
-
@page { size: A4; margin: 18mm; }
|
|
49
|
-
* { box-sizing: border-box; }
|
|
50
|
-
body { margin: 0; font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; color: #111; background: #fff; }
|
|
51
|
-
main { max-width: 174mm; margin: 0 auto; padding: 24px 16px; }
|
|
52
|
-
h1 { font-size: 22px; margin: 0; }
|
|
53
|
-
.muted { color: #555; }
|
|
54
|
-
.head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; border-bottom: 3px solid #111; padding-bottom: 12px; }
|
|
55
|
-
.amount { font-size: 28px; font-weight: 700; text-align: right; }
|
|
56
|
-
.box { border: 1px solid #111; padding: 14px 16px; margin-top: 18px; }
|
|
57
|
-
.label { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #555; }
|
|
58
|
-
.value { font: 700 22px/1.3 ui-monospace, "SF Mono", Menlo, Consolas, monospace; word-break: break-all; letter-spacing: .04em; }
|
|
59
|
-
.bar { margin-top: 18px; text-align: center; }
|
|
60
|
-
.bar svg { max-width: 100%; height: auto; }
|
|
61
|
-
.steps { margin: 18px 0 0; padding-left: 20px; }
|
|
62
|
-
.note { margin-top: 18px; font-size: 12px; }
|
|
63
|
-
.pre { white-space: pre-line; }
|
|
64
|
-
.actions { margin-top: 24px; display: flex; gap: 12px; }
|
|
65
|
-
.actions button { font: inherit; padding: 10px 18px; border: 1px solid #111; background: #111; color: #fff; cursor: pointer; }
|
|
66
|
-
@media print { .actions { display: none; } main { padding: 0; } }
|
|
67
|
-
`;
|
|
68
|
-
function formatMoney(m, locale) {
|
|
69
|
-
if (!m) return "";
|
|
70
|
-
try {
|
|
71
|
-
return new Intl.NumberFormat(locale, { style: "currency", currency: m.currency_code }).format(Number(m.amount));
|
|
72
|
-
} catch {
|
|
73
|
-
return `${m.amount} ${m.currency_code}`;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
function formatDate(iso, locale, timeZone) {
|
|
77
|
-
if (!iso) return "";
|
|
78
|
-
const d = new Date(iso);
|
|
79
|
-
if (Number.isNaN(d.getTime())) return "";
|
|
80
|
-
try {
|
|
81
|
-
return d.toLocaleString(locale, { dateStyle: "long", timeStyle: "short", ...timeZone ? { timeZone } : {} });
|
|
82
|
-
} catch {
|
|
83
|
-
return d.toISOString();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function barcodeSvg(value, label) {
|
|
87
|
-
const g = barcodeGeometry(value);
|
|
88
|
-
if (!g) return null;
|
|
89
|
-
const rects = g.rects.map((r) => `<rect x="${r.x}" y="0" width="${r.w}" height="${g.height}"/>`).join("");
|
|
90
|
-
return `<svg viewBox="0 0 ${g.width} ${g.height}" width="${g.width}" height="${g.height}" role="img" aria-label="${esc(label)} ${esc(value)}" shape-rendering="crispEdges" fill="#000">${rects}</svg>`;
|
|
91
|
-
}
|
|
92
|
-
function renderVoucherDocument(v, opts = {}) {
|
|
93
|
-
const locale = opts.locale ?? "es-MX";
|
|
94
|
-
const t = locale.toLowerCase().startsWith("en") ? EN : ES;
|
|
95
|
-
const shop = opts.shopName || "";
|
|
96
|
-
const method = v.method ? Object.prototype.hasOwnProperty.call(t.methods, v.method.toLowerCase()) ? t.methods[v.method.toLowerCase()] : v.method : t.cash;
|
|
97
|
-
const isSpei = !!v.clabe && !v.reference;
|
|
98
|
-
const code = barcodeValue(v);
|
|
99
|
-
const svg = code ? barcodeSvg(code, t.barcode) : null;
|
|
100
|
-
const expires = formatDate(v.expires_at, locale, opts.timeZone);
|
|
101
|
-
const field = (label, value) => value ? `<div class="box"><div class="label">${esc(label)}</div><div class="value">${esc(value)}</div></div>` : "";
|
|
102
|
-
const steps = isSpei ? t.stepsSpei : t.stepsCash;
|
|
103
|
-
const subtitle = [shop, method, opts.number ? `${t.order} ${opts.number}` : ""].filter(Boolean).map(esc).join(" \xB7 ");
|
|
104
|
-
return `<!doctype html>
|
|
105
|
-
<html lang="${esc(locale)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
106
|
-
<meta name="robots" content="noindex"><title>${esc(t.title)}${shop ? ` - ${esc(shop)}` : ""}</title><style>${CSS}</style></head>
|
|
107
|
-
<body><main>
|
|
108
|
-
<div class="head"><div><h1>${esc(t.title)}</h1><div class="muted">${subtitle}</div></div>
|
|
109
|
-
${v.amount ? `<div><div class="label" style="text-align:right">${esc(t.total)}</div><div class="amount">${esc(formatMoney(v.amount, locale))}</div></div>` : ""}</div>
|
|
110
|
-
${field(t.reference, v.reference)}${field(t.clabe, v.clabe)}
|
|
111
|
-
${svg ? `<div class="bar">${svg}<div class="muted" style="font-family:ui-monospace,monospace">${esc(code)}</div></div>` : ""}
|
|
112
|
-
${expires ? `<p><strong>${esc(t.expires)}:</strong> ${esc(expires)}. ${esc(t.expiresNote)}</p>` : ""}
|
|
113
|
-
<ol class="steps">${steps.map((s) => `<li>${esc(s)}</li>`).join("")}</ol>
|
|
114
|
-
${v.instructions ? `<p class="note pre muted">${esc(v.instructions)}</p>` : ""}
|
|
115
|
-
<p class="note muted">${esc(t.footer)}</p>
|
|
116
|
-
${opts.printButton ? `<div class="actions"><button type="button" id="print">${esc(t.print)}</button></div>` : ""}
|
|
117
|
-
</main>
|
|
118
|
-
${opts.printButton || opts.autoPrint ? `<script${opts.nonce ? ` nonce="${esc(opts.nonce)}"` : ""}>(function(){var b=document.getElementById("print");if(b)b.addEventListener("click",function(){window.print()});${opts.autoPrint ? 'window.addEventListener("load",function(){setTimeout(function(){window.print()},300)});' : ""}})();</script>` : ""}
|
|
119
|
-
</body></html>`;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export { esc, renderVoucherDocument };
|
|
123
|
-
//# sourceMappingURL=voucher-document-SFWJCLTN.js.map
|
|
124
|
-
//# sourceMappingURL=voucher-document-SFWJCLTN.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/account/voucher-document.ts"],"names":[],"mappings":"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","file":"voucher-document-SFWJCLTN.js","sourcesContent":["/**\n * Printable voucher (A4 HTML) that does not depend on any payment gateway: built only from the voucher data OPS keeps.\n * Loaded on demand (the buyer taps print/download) or by `pendingVoucherResponse` on the server; plain text, no React.\n * Everything external passes through `esc` before it enters the HTML.\n */\nimport type { Money } from '@asteby/storefront'\nimport { barcodeGeometry, barcodeValue, type VoucherView } from './voucher.js'\n\nexport function esc(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[c] as string)\n}\n\ntype DocText = {\n title: string\n total: string\n reference: string\n clabe: string\n expires: string\n expiresNote: string\n order: string\n barcode: string\n print: string\n footer: string\n stepsCash: string[]\n stepsSpei: string[]\n methods: Record<string, string>\n cash: string\n}\n\nconst ES: DocText = {\n title: 'Ficha de pago',\n total: 'Total a pagar',\n reference: 'Referencia',\n clabe: 'CLABE',\n expires: 'Vence',\n expiresNote: 'Pasada esa fecha la ficha deja de ser válida.',\n order: 'Pedido',\n barcode: 'Código de barras',\n print: 'Imprimir ficha',\n footer: 'Tu pedido se genera cuando se confirma el pago. Esta ficha es de un solo uso; no la compartas.',\n stepsCash: [\n 'Acude a la tienda OXXO (o el comercio indicado) y di que vas a hacer un pago de servicio en efectivo.',\n 'Muestra el código de barras o dicta la referencia y paga el monto exacto.',\n 'Conserva tu comprobante: confirmaremos tu pago automáticamente.',\n ],\n stepsSpei: ['Entra a la banca en línea o app de tu banco.', 'Haz una transferencia SPEI a la CLABE indicada por el monto exacto.', 'Conserva tu comprobante: confirmaremos tu pago automáticamente.'],\n methods: { oxxo: 'OXXO', spei: 'Transferencia SPEI', bank_transfer: 'Transferencia bancaria', bank_deposit: 'Depósito bancario', cash: 'Pago en efectivo' },\n cash: 'Pago en efectivo',\n}\n\nconst EN: DocText = {\n title: 'Payment voucher',\n total: 'Amount to pay',\n reference: 'Reference',\n clabe: 'CLABE',\n expires: 'Expires',\n expiresNote: 'After that date the voucher is no longer valid.',\n order: 'Order',\n barcode: 'Barcode',\n print: 'Print voucher',\n footer: 'Your order is created when the payment is confirmed. This voucher is single-use; do not share it.',\n stepsCash: [\n 'Go to an OXXO store (or the store indicated) and say you want to make a cash service payment.',\n 'Show the barcode or read out the reference and pay the exact amount.',\n 'Keep your receipt: we will confirm your payment automatically.',\n ],\n stepsSpei: ['Open your bank online or app.', 'Make a SPEI transfer to the CLABE below for the exact amount.', 'Keep your receipt: we will confirm your payment automatically.'],\n methods: { oxxo: 'OXXO', spei: 'SPEI transfer', bank_transfer: 'Bank transfer', bank_deposit: 'Bank deposit', cash: 'Cash payment' },\n cash: 'Cash payment',\n}\n\nexport type VoucherDocumentOptions = {\n shopName?: string\n /** Order number, if there is one yet. */\n number?: string | null\n locale?: string\n /** IANA zone the expiry is printed in (default: the runtime's). */\n timeZone?: string\n /** Print button on screen (hidden when printing). */\n printButton?: boolean\n /** Opens the print dialog on load. */\n autoPrint?: boolean\n /** `<script>` nonce when the one serving the voucher sends a CSP with `script-src 'nonce-…'`. */\n nonce?: string\n}\n\nconst CSS = `\n@page { size: A4; margin: 18mm; }\n* { box-sizing: border-box; }\nbody { margin: 0; font: 14px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; color: #111; background: #fff; }\nmain { max-width: 174mm; margin: 0 auto; padding: 24px 16px; }\nh1 { font-size: 22px; margin: 0; }\n.muted { color: #555; }\n.head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; border-bottom: 3px solid #111; padding-bottom: 12px; }\n.amount { font-size: 28px; font-weight: 700; text-align: right; }\n.box { border: 1px solid #111; padding: 14px 16px; margin-top: 18px; }\n.label { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #555; }\n.value { font: 700 22px/1.3 ui-monospace, \"SF Mono\", Menlo, Consolas, monospace; word-break: break-all; letter-spacing: .04em; }\n.bar { margin-top: 18px; text-align: center; }\n.bar svg { max-width: 100%; height: auto; }\n.steps { margin: 18px 0 0; padding-left: 20px; }\n.note { margin-top: 18px; font-size: 12px; }\n.pre { white-space: pre-line; }\n.actions { margin-top: 24px; display: flex; gap: 12px; }\n.actions button { font: inherit; padding: 10px 18px; border: 1px solid #111; background: #111; color: #fff; cursor: pointer; }\n@media print { .actions { display: none; } main { padding: 0; } }\n`\n\nfunction formatMoney(m: Money | null, locale: string): string {\n if (!m) return ''\n try {\n return new Intl.NumberFormat(locale, { style: 'currency', currency: m.currency_code }).format(Number(m.amount))\n } catch {\n return `${m.amount} ${m.currency_code}`\n }\n}\n\nfunction formatDate(iso: string | null, locale: string, timeZone?: string): string {\n if (!iso) return ''\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return ''\n try {\n return d.toLocaleString(locale, { dateStyle: 'long', timeStyle: 'short', ...(timeZone ? { timeZone } : {}) })\n } catch {\n return d.toISOString()\n }\n}\n\nfunction barcodeSvg(value: string, label: string): string | null {\n const g = barcodeGeometry(value)\n if (!g) return null\n const rects = g.rects.map((r) => `<rect x=\"${r.x}\" y=\"0\" width=\"${r.w}\" height=\"${g.height}\"/>`).join('')\n return `<svg viewBox=\"0 0 ${g.width} ${g.height}\" width=\"${g.width}\" height=\"${g.height}\" role=\"img\" aria-label=\"${esc(label)} ${esc(value)}\" shape-rendering=\"crispEdges\" fill=\"#000\">${rects}</svg>`\n}\n\n/** Complete HTML document of the voucher. Missing data is simply not drawn. */\nexport function renderVoucherDocument(v: VoucherView, opts: VoucherDocumentOptions = {}): string {\n const locale = opts.locale ?? 'es-MX'\n const t = locale.toLowerCase().startsWith('en') ? EN : ES\n const shop = opts.shopName || ''\n // Own keys only: a gateway method named `constructor` or `__proto__` must print as itself, not as Object internals.\n const method = v.method ? (Object.prototype.hasOwnProperty.call(t.methods, v.method.toLowerCase()) ? t.methods[v.method.toLowerCase()]! : v.method) : t.cash\n const isSpei = !!v.clabe && !v.reference\n const code = barcodeValue(v)\n const svg = code ? barcodeSvg(code, t.barcode) : null\n const expires = formatDate(v.expires_at, locale, opts.timeZone)\n const field = (label: string, value: string | null) => (value ? `<div class=\"box\"><div class=\"label\">${esc(label)}</div><div class=\"value\">${esc(value)}</div></div>` : '')\n const steps = isSpei ? t.stepsSpei : t.stepsCash\n const subtitle = [shop, method, opts.number ? `${t.order} ${opts.number}` : ''].filter(Boolean).map(esc).join(' · ')\n return `<!doctype html>\n<html lang=\"${esc(locale)}\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"robots\" content=\"noindex\"><title>${esc(t.title)}${shop ? ` - ${esc(shop)}` : ''}</title><style>${CSS}</style></head>\n<body><main>\n<div class=\"head\"><div><h1>${esc(t.title)}</h1><div class=\"muted\">${subtitle}</div></div>\n${v.amount ? `<div><div class=\"label\" style=\"text-align:right\">${esc(t.total)}</div><div class=\"amount\">${esc(formatMoney(v.amount, locale))}</div></div>` : ''}</div>\n${field(t.reference, v.reference)}${field(t.clabe, v.clabe)}\n${svg ? `<div class=\"bar\">${svg}<div class=\"muted\" style=\"font-family:ui-monospace,monospace\">${esc(code as string)}</div></div>` : ''}\n${expires ? `<p><strong>${esc(t.expires)}:</strong> ${esc(expires)}. ${esc(t.expiresNote)}</p>` : ''}\n<ol class=\"steps\">${steps.map((s) => `<li>${esc(s)}</li>`).join('')}</ol>\n${v.instructions ? `<p class=\"note pre muted\">${esc(v.instructions)}</p>` : ''}\n<p class=\"note muted\">${esc(t.footer)}</p>\n${opts.printButton ? `<div class=\"actions\"><button type=\"button\" id=\"print\">${esc(t.print)}</button></div>` : ''}\n</main>\n${opts.printButton || opts.autoPrint ? `<script${opts.nonce ? ` nonce=\"${esc(opts.nonce)}\"` : ''}>(function(){var b=document.getElementById(\"print\");if(b)b.addEventListener(\"click\",function(){window.print()});${opts.autoPrint ? 'window.addEventListener(\"load\",function(){setTimeout(function(){window.print()},300)});' : ''}})();</script>` : ''}\n</body></html>`\n}\n"]}
|