@qrdx/cli 0.0.7 → 0.0.8
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/index.js +11 -38
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { readFileSync, mkdirSync, writeFileSync, createReadStream } from 'fs';
|
|
|
3
3
|
import { join, resolve, extname } from 'path';
|
|
4
4
|
import { readFile } from 'fs/promises';
|
|
5
5
|
import { BODY_PATTERN, CORNER_EYE_PATTERNS, CORNER_EYE_DOT_PATTERNS, getTemplateIds, FRAME_STYLES, DEFAULT_FRAME_TEXT, FRAME_TEXT_MAX_LENGTH, DEFAULT_MARGIN, getFrameDimensions, colorConfigSchema, errorLevelSchema, QRCodeSVG, svgToEPS } from 'qrdx';
|
|
6
|
+
import { getQRAsPNG } from 'qrdx/node';
|
|
6
7
|
import { createElement } from 'react';
|
|
7
8
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
8
9
|
import * as readline from 'readline';
|
|
@@ -138,7 +139,6 @@ var OUTPUT_FORMATS = [
|
|
|
138
139
|
"webp",
|
|
139
140
|
"eps"
|
|
140
141
|
];
|
|
141
|
-
var encodeRaster = (image, format) => format === "webp" ? image.webp({ lossless: true }) : image.png();
|
|
142
142
|
function buildSVGString(props) {
|
|
143
143
|
const element = createElement(QRCodeSVG, {
|
|
144
144
|
size: props.size ?? 512,
|
|
@@ -198,24 +198,6 @@ async function buildEPSString(props) {
|
|
|
198
198
|
}
|
|
199
199
|
return await svgToEPS(buildSVGString(epsProps));
|
|
200
200
|
}
|
|
201
|
-
async function findLogoBox(sharp, svgString) {
|
|
202
|
-
const imageTag = svgString.match(/<image\b[^>]*?(?:\/>|><\/image>)/)?.[0];
|
|
203
|
-
if (!imageTag) {
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
const markerTag = imageTag.replace(/^<image\b/, '<rect class="qrdx-logo-box"').replace(/\shref="[^"]*"/, "").replace(/(?:\/>|><\/image>)$/, ' fill="#000"/>');
|
|
207
|
-
const markerSvg = svgString.replace(imageTag, markerTag).replace(
|
|
208
|
-
/<svg\b[^>]*>/,
|
|
209
|
-
(open) => `${open}<style>*{visibility:hidden}.qrdx-logo-box{visibility:visible}</style>`
|
|
210
|
-
);
|
|
211
|
-
const { info } = await sharp(Buffer.from(markerSvg, "utf-8")).png().trim().toBuffer({ resolveWithObject: true });
|
|
212
|
-
return {
|
|
213
|
-
left: -(info.trimOffsetLeft ?? 0),
|
|
214
|
-
top: -(info.trimOffsetTop ?? 0),
|
|
215
|
-
width: info.width,
|
|
216
|
-
height: info.height
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
201
|
async function saveOutput(options) {
|
|
220
202
|
const { outputPath, format, ...qrProps } = options;
|
|
221
203
|
const svgString = buildSVGString(qrProps);
|
|
@@ -229,33 +211,24 @@ ${svgString}`;
|
|
|
229
211
|
writeFileSync(outputPath, await buildEPSString(qrProps), "utf-8");
|
|
230
212
|
return;
|
|
231
213
|
}
|
|
214
|
+
const pngBytes = await getQRAsPNG(qrProps, {
|
|
215
|
+
size: qrProps.size ?? 512,
|
|
216
|
+
loadExternalLogos: true
|
|
217
|
+
});
|
|
218
|
+
if (format === "png") {
|
|
219
|
+
writeFileSync(outputPath, pngBytes);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
232
222
|
let sharp;
|
|
233
223
|
try {
|
|
234
224
|
const mod = await import('sharp');
|
|
235
225
|
sharp = mod.default;
|
|
236
226
|
} catch {
|
|
237
227
|
throw new Error(
|
|
238
|
-
|
|
228
|
+
"WebP output needs the sharp package (native binaries). It is optional and may not have installed; use SVG or reinstall: https://sharp.pixelplumbing.com/install"
|
|
239
229
|
);
|
|
240
230
|
}
|
|
241
|
-
|
|
242
|
-
const size = qrProps.size ?? 512;
|
|
243
|
-
const { width, height } = getFrameDimensions(size, qrProps.frame);
|
|
244
|
-
const qrImage = sharp(svgBuffer).resize(
|
|
245
|
-
Math.round(width),
|
|
246
|
-
Math.round(height)
|
|
247
|
-
);
|
|
248
|
-
const logoSrc = qrProps.imageSettings?.src;
|
|
249
|
-
const box = logoSrc ? await findLogoBox(sharp, svgString) : null;
|
|
250
|
-
if (!(logoSrc && box)) {
|
|
251
|
-
await encodeRaster(qrImage, format).toFile(outputPath);
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
const logo = await sharp(await loadLogo(logoSrc)).resize(box.width, box.height, { fit: "fill" }).png().toBuffer();
|
|
255
|
-
const composited = sharp(await qrImage.png().toBuffer()).composite([
|
|
256
|
-
{ input: logo, left: box.left, top: box.top }
|
|
257
|
-
]);
|
|
258
|
-
await encodeRaster(composited, format).toFile(outputPath);
|
|
231
|
+
await sharp(Buffer.from(pngBytes)).webp({ lossless: true }).toFile(outputPath);
|
|
259
232
|
}
|
|
260
233
|
var RESET = "\x1B[0m";
|
|
261
234
|
var TEXT = "\x1B[38;5;145m";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qrdx/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "QR code generator CLI for developers: styled SVG, PNG, WebP and vector EPS QR codes from the command line",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"qr-code",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@clack/prompts": "^1.8.1",
|
|
47
47
|
"picocolors": "^1.1.1",
|
|
48
|
-
"qrdx": "0.0.
|
|
48
|
+
"qrdx": "0.0.50",
|
|
49
49
|
"react": "19.3.1",
|
|
50
50
|
"react-dom": "19.3.1"
|
|
51
51
|
},
|