@poe-platform/safe-bash 0.1.843 → 0.1.845
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/safe-bash/command-chunks/{chunk-MJB4WWYP.js → chunk-4KM2VJRB.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-SBBMNLD6.js → chunk-CMGVQM4Y.js} +15 -5
- package/dist/safe-bash-command-ffmpeg/index.js +1336 -1115
- package/dist/safe-bash-command-ffprobe/index.js +2 -2
- package/dist/safe-bash-command-ffprobe/media.js +2 -2
- package/dist/safe-bash-command-imagemagick/index.d.ts +1 -0
- package/dist/safe-bash-command-imagemagick/index.js +138 -98
- package/package.json +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createFfprobeCommand
|
|
3
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
3
|
+
} from "../safe-bash/command-chunks/chunk-4KM2VJRB.js";
|
|
4
4
|
import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
|
|
5
|
-
import "../safe-bash/command-chunks/chunk-
|
|
5
|
+
import "../safe-bash/command-chunks/chunk-CMGVQM4Y.js";
|
|
6
6
|
import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
|
|
7
7
|
|
|
8
8
|
// packages/safe-bash-command-ffprobe/src/index.ts
|
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
loadManifestResources,
|
|
12
12
|
resolvePath,
|
|
13
13
|
rethrowRuntimeError
|
|
14
|
-
} from "../safe-bash/command-chunks/chunk-
|
|
14
|
+
} from "../safe-bash/command-chunks/chunk-4KM2VJRB.js";
|
|
15
15
|
import "../safe-bash/command-chunks/chunk-MGBHGZEX.js";
|
|
16
|
-
import "../safe-bash/command-chunks/chunk-
|
|
16
|
+
import "../safe-bash/command-chunks/chunk-CMGVQM4Y.js";
|
|
17
17
|
import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
|
|
18
18
|
export {
|
|
19
19
|
createFfprobeCommand,
|
|
@@ -36,6 +36,7 @@ export interface MagickGeometry {
|
|
|
36
36
|
readonly percentY?: number;
|
|
37
37
|
readonly areaLimit?: number;
|
|
38
38
|
readonly isSubdivide?: boolean;
|
|
39
|
+
readonly aspectRatio?: number;
|
|
39
40
|
}
|
|
40
41
|
export declare function parseMagickGeometry(raw: string): MagickGeometry;
|
|
41
42
|
export declare function runIdentifyCli(argv: readonly string[], files: Map<string, Uint8Array> | IdentifyFileInput, stdinBytes?: Uint8Array, signal?: AbortSignal): Promise<ImageMagickCliResult>;
|
|
@@ -1273,10 +1273,10 @@ function* combinePixelSteps(size, lengths) {
|
|
|
1273
1273
|
for (let offset = 3; offset < length; offset += 4) data[offset] = 255;
|
|
1274
1274
|
continue;
|
|
1275
1275
|
}
|
|
1276
|
-
const count = Math.max(0, Math.min(length, lengths[image] - position));
|
|
1276
|
+
const count = Math.max(0, Math.min(length, (lengths[image] ?? 0) - position));
|
|
1277
1277
|
if (!count) continue;
|
|
1278
1278
|
const source = yield { kind: "read", image, position, length: count };
|
|
1279
|
-
for (let offset = 0; offset < count; offset += 4) data[offset + image] = source[offset];
|
|
1279
|
+
for (let offset = 0; offset < count; offset += 4) data[offset + image] = Math.round(0.212656 * source[offset] + 0.715158 * source[offset + 1] + 0.072186 * source[offset + 2]);
|
|
1280
1280
|
}
|
|
1281
1281
|
yield { kind: "write", position, data };
|
|
1282
1282
|
}
|
|
@@ -3947,6 +3947,13 @@ function parseMagickGeometry(raw) {
|
|
|
3947
3947
|
break;
|
|
3948
3948
|
}
|
|
3949
3949
|
}
|
|
3950
|
+
if (s.includes(":")) {
|
|
3951
|
+
const parts = s.split(":");
|
|
3952
|
+
const ratio = Number(parts[0]) / Number(parts[1]);
|
|
3953
|
+
if (parts.length === 2 && Number(parts[0]) > 0 && Number(parts[1]) > 0 && Number.isFinite(ratio)) {
|
|
3954
|
+
return { aspectRatio: ratio, x, y, hasOffset, forceExact, shrinkOnly, enlargeOnly, fillArea, isPercent: false };
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3950
3957
|
if (isArea) {
|
|
3951
3958
|
if (s.includes("x") || s.includes("X")) {
|
|
3952
3959
|
const [wStr, hStr] = s.split(/[xX]/);
|
|
@@ -4803,14 +4810,16 @@ function* createCheckerboardImageSteps(width, height) {
|
|
|
4803
4810
|
function* applyMagickSpliceSteps(img, geomStr, bg, gravity = "northwest", signal) {
|
|
4804
4811
|
let cooperativeWork = 0;
|
|
4805
4812
|
const g = parseMagickGeometry(geomStr);
|
|
4806
|
-
const sw = Math.max(0, Math.round(g.width ?? 0));
|
|
4807
|
-
const sh = Math.max(0, Math.round(g.height ?? 0));
|
|
4813
|
+
const sw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? img.width / 100 : 1)));
|
|
4814
|
+
const sh = Math.max(0, Math.round((g.height ?? 0) * (g.isPercent ? img.height / 100 : 1)));
|
|
4808
4815
|
const box = gravityAdjustBox(img.width, img.height, sw, sh, g.x, g.y, gravity);
|
|
4809
4816
|
const anchor = resolveGravityOffset(sw, sh, gravity);
|
|
4810
|
-
const sx = Math.max(0, Math.min(img.width, box.x + anchor.left));
|
|
4811
|
-
const sy = Math.max(0, Math.min(img.height, box.y + anchor.top));
|
|
4812
4817
|
const outW = img.width + sw;
|
|
4813
4818
|
const outH = img.height + sh;
|
|
4819
|
+
const xOffset = box.x + anchor.left;
|
|
4820
|
+
const sx = xOffset < 0 || xOffset > img.width ? outW : xOffset;
|
|
4821
|
+
if (box.y + anchor.top > outH) throw new Error("pixels are not authentic");
|
|
4822
|
+
const sy = Math.max(0, Math.min(img.height, box.y + anchor.top));
|
|
4814
4823
|
const out = new Uint8Array(new ArrayBuffer(outW * outH * 4 + outH), 0, outW * outH * 4);
|
|
4815
4824
|
for (let y = 0; y < outH; y++) {
|
|
4816
4825
|
if (++cooperativeWork % 65536 === 0)
|
|
@@ -4825,7 +4834,7 @@ function* applyMagickSpliceSteps(img, geomStr, bg, gravity = "northwest", signal
|
|
|
4825
4834
|
out[dstIdx + 2] = bg.b;
|
|
4826
4835
|
out[dstIdx + 3] = bg.a;
|
|
4827
4836
|
} else {
|
|
4828
|
-
const origX = x < sx ? x : x - sw;
|
|
4837
|
+
const origX = Math.min(img.width - 1, x < sx ? x : x - sw);
|
|
4829
4838
|
const origY = y < sy ? y : y - sh;
|
|
4830
4839
|
const srcIdx = (origY * img.width + origX) * 4;
|
|
4831
4840
|
out[dstIdx] = img.data[srcIdx];
|
|
@@ -4840,8 +4849,8 @@ function* applyMagickSpliceSteps(img, geomStr, bg, gravity = "northwest", signal
|
|
|
4840
4849
|
function* applyMagickChopSteps(img, geomStr, gravity = "northwest", signal) {
|
|
4841
4850
|
let cooperativeWork = 0;
|
|
4842
4851
|
const g = parseMagickGeometry(geomStr);
|
|
4843
|
-
const cw = Math.max(0, Math.round(g.width ?? 0));
|
|
4844
|
-
const ch = Math.max(0, Math.round(g.height ?? 0));
|
|
4852
|
+
const cw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? img.width / 100 : 1)));
|
|
4853
|
+
const ch = Math.max(0, Math.round((g.height ?? 0) * (g.isPercent ? img.height / 100 : 1)));
|
|
4845
4854
|
const { x: x0, y: y0 } = gravityAdjustBox(img.width, img.height, cw, ch, g.x, g.y, gravity);
|
|
4846
4855
|
if (x0 + cw < 0 || y0 + ch < 0 || x0 > img.width || y0 > img.height) {
|
|
4847
4856
|
return img;
|
|
@@ -4879,6 +4888,7 @@ function* applyMagickChopSteps(img, geomStr, gravity = "northwest", signal) {
|
|
|
4879
4888
|
}
|
|
4880
4889
|
function parseMagickRollGeometry(raw) {
|
|
4881
4890
|
const geometry = parseMagickGeometry(raw);
|
|
4891
|
+
if (geometry.isPercent) return { ...geometry, x: 0, y: 0 };
|
|
4882
4892
|
if (geometry.hasOffset && geometry.width !== void 0 && !raw.toLowerCase().includes("x")) {
|
|
4883
4893
|
throw new Error(`invalid argument for option '-roll': ${raw}`);
|
|
4884
4894
|
}
|
|
@@ -6897,13 +6907,12 @@ function magickCropArea(img, geomStr, gravity) {
|
|
|
6897
6907
|
}
|
|
6898
6908
|
function magickExtentLayout(img, geomStr, state) {
|
|
6899
6909
|
const g = parseMagickGeometry(geomStr);
|
|
6900
|
-
const targetW = Math.max(1, Math.round(g.width ?? img.width));
|
|
6901
|
-
const targetH = Math.max(1, Math.round(g.height ?? img.height));
|
|
6902
|
-
|
|
6903
|
-
const
|
|
6904
|
-
const
|
|
6905
|
-
const
|
|
6906
|
-
const top = Math.round(offset.top - (isSouth ? -g.y : g.y));
|
|
6910
|
+
const targetW = Math.max(1, Math.round(g.aspectRatio !== void 0 ? Math.min(img.width, img.height * g.aspectRatio) : g.isPercent ? img.width * (g.percentX ?? 100) / 100 : g.width ?? img.width));
|
|
6911
|
+
const targetH = Math.max(1, Math.round(g.aspectRatio !== void 0 ? Math.min(img.height, img.width / g.aspectRatio) : g.isPercent ? img.height * (g.percentY ?? 100) / 100 : g.height ?? img.height));
|
|
6912
|
+
if (g.enlargeOnly && img.width > targetW && img.height > targetH || g.shrinkOnly && img.width < targetW && img.height < targetH) return void 0;
|
|
6913
|
+
const offset = gravityAdjustBox(img.width, img.height, targetW, targetH, g.x, g.y, state.gravity);
|
|
6914
|
+
const left = -offset.x;
|
|
6915
|
+
const top = -offset.y;
|
|
6907
6916
|
const dstX0 = Math.max(0, left);
|
|
6908
6917
|
const dstY0 = Math.max(0, top);
|
|
6909
6918
|
const dstX1 = Math.min(targetW, left + img.width);
|
|
@@ -6913,6 +6922,7 @@ function magickExtentLayout(img, geomStr, state) {
|
|
|
6913
6922
|
function* applyMagickExtentSteps(img, geomStr, state, signal) {
|
|
6914
6923
|
yield;
|
|
6915
6924
|
const layout = magickExtentLayout(img, geomStr, state);
|
|
6925
|
+
if (!layout) return img;
|
|
6916
6926
|
const virtualCanvas = magickResizeCanvas(img, layout.width, layout.height);
|
|
6917
6927
|
const source = img[magickInput];
|
|
6918
6928
|
const canvas = {
|
|
@@ -7797,32 +7807,37 @@ function runIdentifyCliSync(argv, files, stdinBytes, signal) {
|
|
|
7797
7807
|
}
|
|
7798
7808
|
return next.value;
|
|
7799
7809
|
}
|
|
7800
|
-
function
|
|
7810
|
+
function parseMagickIndices(spec, ranges = true) {
|
|
7811
|
+
if (!spec.trim() || spec.trimStart().startsWith(",")) throw new Error(`invalid argument ${spec}`);
|
|
7812
|
+
return spec.split(",").filter((part) => part.trim()).map((part) => {
|
|
7813
|
+
const value = part.trim();
|
|
7814
|
+
const separator = ranges ? value.indexOf("-", 1) : -1;
|
|
7815
|
+
const values = separator > 0 ? [value.slice(0, separator), value.slice(separator + 1)] : [value];
|
|
7816
|
+
return values.map((value2) => {
|
|
7817
|
+
const digits = value2.startsWith("-") ? value2.slice(1) : value2;
|
|
7818
|
+
if (!digits.length || !Array.from(digits).every((c) => c >= "0" && c <= "9") || !Number.isSafeInteger(Number(value2))) {
|
|
7819
|
+
throw new Error(`invalid argument ${spec}`);
|
|
7820
|
+
}
|
|
7821
|
+
return Number(value2);
|
|
7822
|
+
});
|
|
7823
|
+
});
|
|
7824
|
+
}
|
|
7825
|
+
function* parseMagickIndexSpec(spec, length, operation) {
|
|
7826
|
+
const parts = parseMagickIndices(spec);
|
|
7801
7827
|
if (length <= 0) return;
|
|
7802
7828
|
const resolve = (n) => n < 0 ? Math.max(0, length + n) : Math.min(Math.max(0, n), length - 1);
|
|
7803
|
-
for (const
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
};
|
|
7811
|
-
const rangeMatch = separator > 0 && integer(trimmed.slice(0, separator)) && integer(trimmed.slice(separator + 1)) ? [trimmed, trimmed.slice(0, separator), trimmed.slice(separator + 1)] : void 0;
|
|
7812
|
-
if (rangeMatch) {
|
|
7813
|
-
const s = resolve(parseInt(rangeMatch[1], 10));
|
|
7814
|
-
const e = resolve(parseInt(rangeMatch[2], 10));
|
|
7815
|
-
if (s <= e) {
|
|
7816
|
-
for (let k = s; k <= e; k++) yield k;
|
|
7817
|
-
} else {
|
|
7818
|
-
for (let k = s; k >= e; k--) yield k;
|
|
7829
|
+
for (const [num, end] of parts) {
|
|
7830
|
+
if (end !== void 0) {
|
|
7831
|
+
const s = resolve(num), e = resolve(end), step = s <= e ? 1 : -1;
|
|
7832
|
+
if (operation === "delete" && s > e) continue;
|
|
7833
|
+
for (let k = s; ; k += step) {
|
|
7834
|
+
yield k;
|
|
7835
|
+
if (k === e) break;
|
|
7819
7836
|
}
|
|
7820
7837
|
} else {
|
|
7821
|
-
const
|
|
7822
|
-
if (
|
|
7823
|
-
|
|
7824
|
-
if (idx >= 0 && idx < length) yield idx;
|
|
7825
|
-
}
|
|
7838
|
+
const idx = num < 0 ? length + num : num;
|
|
7839
|
+
if (idx >= 0 && idx < length) yield idx;
|
|
7840
|
+
else if (operation === "clone") throw new Error(`invalid image index ${num}`);
|
|
7826
7841
|
}
|
|
7827
7842
|
}
|
|
7828
7843
|
}
|
|
@@ -8619,7 +8634,7 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8619
8634
|
} else return void 0;
|
|
8620
8635
|
return i;
|
|
8621
8636
|
}
|
|
8622
|
-
function* evaluatePipelineTokensSteps(tokens, files, state, parentStack
|
|
8637
|
+
function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBytes, signal, analysis = { text: "", warnings: "" }) {
|
|
8623
8638
|
let cooperativeWork = 63;
|
|
8624
8639
|
let stack = [];
|
|
8625
8640
|
let operandsOnly = false;
|
|
@@ -8944,18 +8959,22 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], st
|
|
|
8944
8959
|
return { ...canvas, virtualCanvas: magickBorderCanvas(im, bw, bh) };
|
|
8945
8960
|
});
|
|
8946
8961
|
} else if (t === "-shave") {
|
|
8947
|
-
const
|
|
8962
|
+
const geometry = tokens[++i] ?? "0x0";
|
|
8963
|
+
const g = parseMagickGeometry(geometry);
|
|
8948
8964
|
const sw = Math.max(0, Math.round(g.width ?? 0));
|
|
8949
8965
|
const sh = Math.max(0, Math.round(g.height ?? sw));
|
|
8950
8966
|
stack = yield* mapSteps(stack, function* (im) {
|
|
8951
|
-
|
|
8952
|
-
|
|
8967
|
+
if (sw * 2 >= im.width || sh * 2 >= im.height) {
|
|
8968
|
+
analysis.warnings += `magick: geometry does not contain image '${geometry}'
|
|
8969
|
+
`;
|
|
8970
|
+
return im;
|
|
8971
|
+
}
|
|
8953
8972
|
return { ...yield* extractImageSteps2(im, {
|
|
8954
|
-
left:
|
|
8955
|
-
top:
|
|
8956
|
-
width:
|
|
8957
|
-
height:
|
|
8958
|
-
}), virtualCanvas: magickBorderCanvas(im, -
|
|
8973
|
+
left: sw,
|
|
8974
|
+
top: sh,
|
|
8975
|
+
width: im.width - sw * 2,
|
|
8976
|
+
height: im.height - sh * 2
|
|
8977
|
+
}), virtualCanvas: magickBorderCanvas(im, -sw, -sh) };
|
|
8959
8978
|
});
|
|
8960
8979
|
} else if (t === "-trim") {
|
|
8961
8980
|
stack = yield* mapSteps(stack, function* (im) {
|
|
@@ -9077,14 +9096,11 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], st
|
|
|
9077
9096
|
}
|
|
9078
9097
|
stack = nextStack;
|
|
9079
9098
|
} else if (t === "-combine") {
|
|
9080
|
-
if (stack.length
|
|
9099
|
+
if (stack.length > 0) {
|
|
9081
9100
|
const rIm = stack[0];
|
|
9082
|
-
const
|
|
9083
|
-
const bIm = stack[2] ?? rIm;
|
|
9084
|
-
const aIm = stack[3];
|
|
9085
|
-
const sources = [rIm, gIm, bIm, ...aIm ? [aIm] : []];
|
|
9101
|
+
const sources = stack.slice(0, 4);
|
|
9086
9102
|
const result = yield* applyMagickRasterSteps(rIm, combinePixelSteps(rIm.width * rIm.height * 4, sources.map((image) => image.data.length)), signal, rIm, sources);
|
|
9087
|
-
stack = [{ ...result, space: "srgb", channels: 4, hasAlpha:
|
|
9103
|
+
stack = [{ ...result, space: "srgb", channels: 4, hasAlpha: sources.length === 4 }];
|
|
9088
9104
|
}
|
|
9089
9105
|
} else if (t === "-draw") {
|
|
9090
9106
|
const drawSpec = tokens[++i] ?? "";
|
|
@@ -9115,9 +9131,10 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], st
|
|
|
9115
9131
|
return yield* applyMagickRasterSteps(im, annotatePixelSteps(im, offset, text, state), signal);
|
|
9116
9132
|
});
|
|
9117
9133
|
} else if (t === "+clone" || t === "-clone") {
|
|
9118
|
-
const sourcePool =
|
|
9134
|
+
const sourcePool = parentStack ?? stack;
|
|
9135
|
+
if (sourcePool.length === 0) throw new Error(`UnableToCloneImage ${t}`);
|
|
9119
9136
|
const spec = t === "+clone" ? "-1" : tokens[++i] ?? "-1";
|
|
9120
|
-
for (const idx of parseMagickIndexSpec(spec, sourcePool.length)) {
|
|
9137
|
+
for (const idx of parseMagickIndexSpec(spec, sourcePool.length, "clone")) {
|
|
9121
9138
|
if (++cooperativeWork % 65536 === 0)
|
|
9122
9139
|
yield;
|
|
9123
9140
|
const chosen = sourcePool[idx];
|
|
@@ -9125,27 +9142,23 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], st
|
|
|
9125
9142
|
stack.push({ ...chosen, data: new Uint8Array(chosen.data) });
|
|
9126
9143
|
}
|
|
9127
9144
|
} else if (t === "-duplicate" || t === "+duplicate") {
|
|
9145
|
+
if (stack.length === 0) throw new Error(`no images found for operation ${t}`);
|
|
9128
9146
|
let count = 1;
|
|
9129
9147
|
let idxSpec = "-1";
|
|
9130
9148
|
if (t === "-duplicate") {
|
|
9131
|
-
const
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
count = Math.max(0, parseInt(nextTok, 10));
|
|
9140
|
-
}
|
|
9141
|
-
}
|
|
9142
|
-
}
|
|
9143
|
-
const sourcePool = stack.length > 0 ? stack : parentStack;
|
|
9149
|
+
const value = tokens[++i] ?? "", comma = value.indexOf(",");
|
|
9150
|
+
const countSpec = comma < 0 ? value : value.slice(0, comma);
|
|
9151
|
+
count = parseInt(countSpec, 10);
|
|
9152
|
+
if (!Number.isSafeInteger(count) || count < 0) throw new Error(`invalid argument ${value}`);
|
|
9153
|
+
idxSpec = comma < 0 ? "-1" : value.slice(comma + 1) || "-1";
|
|
9154
|
+
parseMagickIndices(idxSpec);
|
|
9155
|
+
}
|
|
9156
|
+
const sourcePool = stack;
|
|
9144
9157
|
const sourceLength = sourcePool.length;
|
|
9145
9158
|
for (let k = 0; k < count; k++) {
|
|
9146
9159
|
if (++cooperativeWork % 65536 === 0)
|
|
9147
9160
|
yield;
|
|
9148
|
-
for (const idx of parseMagickIndexSpec(idxSpec, sourceLength)) {
|
|
9161
|
+
for (const idx of parseMagickIndexSpec(idxSpec, sourceLength, "clone")) {
|
|
9149
9162
|
if (++cooperativeWork % 65536 === 0)
|
|
9150
9163
|
yield;
|
|
9151
9164
|
const chosen = sourcePool[idx];
|
|
@@ -9155,30 +9168,30 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], st
|
|
|
9155
9168
|
}
|
|
9156
9169
|
} else if (t === "+insert" || t === "-insert") {
|
|
9157
9170
|
const rawIdx = t === "+insert" ? 0 : Number(tokens[++i] ?? 0);
|
|
9171
|
+
const target = rawIdx < 0 ? stack.length - 1 + rawIdx : rawIdx;
|
|
9172
|
+
if (!Number.isInteger(target) || target < 0 || target >= stack.length || rawIdx < 0 && target === 0) throw new Error(`invalid image index ${t}`);
|
|
9158
9173
|
if (stack.length > 1) {
|
|
9159
9174
|
const last = stack.pop();
|
|
9160
|
-
const target = rawIdx < 0 ? Math.max(0, stack.length + 1 + rawIdx) : Math.min(stack.length, Math.max(0, rawIdx));
|
|
9161
9175
|
stack.splice(target, 0, last);
|
|
9162
9176
|
}
|
|
9163
9177
|
} else if (t === "+swap" || t === "-swap") {
|
|
9164
9178
|
let i1 = stack.length - 2;
|
|
9165
9179
|
let i2 = stack.length - 1;
|
|
9166
9180
|
if (t === "-swap") {
|
|
9167
|
-
const [s1, s2] = (tokens[++i] ?? "-2,-1"
|
|
9181
|
+
const [s1, s2] = parseMagickIndices(tokens[++i] ?? "-2,-1", false).flat();
|
|
9168
9182
|
i1 = (s1 ?? -2) < 0 ? stack.length + (s1 ?? -2) : s1 ?? 0;
|
|
9169
9183
|
i2 = (s2 ?? -1) < 0 ? stack.length + (s2 ?? -1) : s2 ?? 0;
|
|
9170
9184
|
}
|
|
9171
|
-
if (stack[i1]
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
}
|
|
9185
|
+
if (i1 === i2 || !stack[i1] || !stack[i2]) throw new Error(`invalid image index ${t}`);
|
|
9186
|
+
const tmp = stack[i1];
|
|
9187
|
+
stack[i1] = stack[i2];
|
|
9188
|
+
stack[i2] = tmp;
|
|
9176
9189
|
} else if (t === "+delete" || t === "-delete") {
|
|
9177
9190
|
if (t === "+delete") {
|
|
9178
9191
|
const popped = stack.pop();
|
|
9179
9192
|
if (popped) detachRgbaBuffer(popped.data);
|
|
9180
9193
|
} else {
|
|
9181
|
-
const toDelete = new Set(parseMagickIndexSpec(tokens[++i] ?? "-1", stack.length));
|
|
9194
|
+
const toDelete = new Set(parseMagickIndexSpec(tokens[++i] ?? "-1", stack.length, "delete"));
|
|
9182
9195
|
stack = stack.filter((im, idx) => {
|
|
9183
9196
|
if (toDelete.has(idx)) {
|
|
9184
9197
|
detachRgbaBuffer(im.data);
|
|
@@ -9335,7 +9348,7 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9335
9348
|
const pipelineTokens = argv.slice(0, -1);
|
|
9336
9349
|
const state = createDefaultState();
|
|
9337
9350
|
try {
|
|
9338
|
-
const stack = yield* evaluatePipelineTokensSteps(pipelineTokens, files, state,
|
|
9351
|
+
const stack = yield* evaluatePipelineTokensSteps(pipelineTokens, files, state, void 0, stdinBytes, signal, analysis);
|
|
9339
9352
|
if (stack.length === 0) {
|
|
9340
9353
|
return {
|
|
9341
9354
|
exitCode: 1,
|
|
@@ -9525,17 +9538,21 @@ async function transformStoredMagickCoordinates(image, backend, token, geometry,
|
|
|
9525
9538
|
xs = [{ source: w - dx, target: 0, length: dx }, { source: 0, target: dx, length: w - dx }];
|
|
9526
9539
|
ys = [{ source: h - dy, target: 0, length: dy }, { source: 0, target: dy, length: h - dy }];
|
|
9527
9540
|
} else if (token === "-splice") {
|
|
9528
|
-
const sw = Math.max(0, Math.round(g.width ?? 0)
|
|
9541
|
+
const sw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? w / 100 : 1)));
|
|
9542
|
+
const sh = Math.max(0, Math.round((g.height ?? 0) * (g.isPercent ? h / 100 : 1)));
|
|
9529
9543
|
const box = gravityAdjustBox(w, h, sw, sh, g.x, g.y, state.gravity);
|
|
9530
9544
|
const anchor = resolveGravityOffset(sw, sh, state.gravity);
|
|
9531
|
-
const x = Math.max(0, Math.min(w, box.x + anchor.left));
|
|
9532
|
-
const y = Math.max(0, Math.min(h, box.y + anchor.top));
|
|
9533
9545
|
width += sw;
|
|
9534
9546
|
height += sh;
|
|
9535
|
-
|
|
9547
|
+
const xOffset = box.x + anchor.left;
|
|
9548
|
+
const x = xOffset < 0 || xOffset > w ? width : xOffset;
|
|
9549
|
+
if (box.y + anchor.top > height) throw new Error("pixels are not authentic");
|
|
9550
|
+
const y = Math.max(0, Math.min(h, box.y + anchor.top));
|
|
9551
|
+
xs = [{ source: 0, target: 0, length: x }, { source: x, target: x + sw, length: Math.max(0, w - x) }];
|
|
9536
9552
|
ys = [{ source: 0, target: 0, length: y }, { source: y, target: y + sh, length: h - y }];
|
|
9537
9553
|
} else {
|
|
9538
|
-
const cw = Math.max(0, Math.round(g.width ?? 0)
|
|
9554
|
+
const cw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? w / 100 : 1)));
|
|
9555
|
+
const ch = Math.max(0, Math.round((g.height ?? 0) * (g.isPercent ? h / 100 : 1)));
|
|
9539
9556
|
const { x, y } = gravityAdjustBox(w, h, cw, ch, g.x, g.y, state.gravity);
|
|
9540
9557
|
if (x + cw < 0 || y + ch < 0 || x > w || y > h) return image;
|
|
9541
9558
|
const x0 = Math.max(0, Math.min(w, x)), x1 = Math.max(x0, Math.min(w, x + cw));
|
|
@@ -9552,7 +9569,16 @@ async function transformStoredMagickCoordinates(image, backend, token, geometry,
|
|
|
9552
9569
|
for (let offset = 0; offset < x.length; offset += 4096) {
|
|
9553
9570
|
if (work++ % 64 === 0) await yieldTurn11(signal);
|
|
9554
9571
|
const length = Math.min(4096, x.length - offset) * 4;
|
|
9555
|
-
const
|
|
9572
|
+
const sourceX = Math.min(w - 1, x.source + offset);
|
|
9573
|
+
const sourceLength = Math.min(length, (w - sourceX) * 4);
|
|
9574
|
+
let bytes = await backend.storage.read(image.position + ((y.source + row) * w + sourceX) * 4, sourceLength);
|
|
9575
|
+
if (sourceLength < length) {
|
|
9576
|
+
const extended = new Uint8Array(length);
|
|
9577
|
+
extended.set(bytes);
|
|
9578
|
+
const edge = bytes.subarray(sourceLength - 4);
|
|
9579
|
+
for (let i = sourceLength; i < length; i += 4) extended.set(edge, i);
|
|
9580
|
+
bytes = extended;
|
|
9581
|
+
}
|
|
9556
9582
|
await backend.storage.write(position + ((y.target + row) * width + x.target + offset) * 4, bytes);
|
|
9557
9583
|
}
|
|
9558
9584
|
}
|
|
@@ -9686,34 +9712,42 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9686
9712
|
if (!operandsOnly && ["+clone", "-clone", "+duplicate", "-duplicate", "+delete", "-delete", "+swap", "-swap", "-reverse", "+insert", "-insert"].includes(token)) {
|
|
9687
9713
|
let spec = "-1", count = 1;
|
|
9688
9714
|
if (["-clone", "-delete", "-swap", "-insert"].includes(token)) spec = tokens[++i] ?? (token === "-swap" ? "-2,-1" : token === "-insert" ? "0" : "-1");
|
|
9689
|
-
if (token === "-duplicate"
|
|
9690
|
-
const value = tokens[++i], comma = value.indexOf(",");
|
|
9691
|
-
count =
|
|
9715
|
+
if (token === "-duplicate") {
|
|
9716
|
+
const value = tokens[++i] ?? "", comma = value.indexOf(",");
|
|
9717
|
+
count = parseInt(value, 10);
|
|
9718
|
+
if (!Number.isSafeInteger(count) || count < 0) throw new Error(`invalid argument ${value}`);
|
|
9692
9719
|
spec = comma < 0 ? "-1" : value.slice(comma + 1) || "-1";
|
|
9720
|
+
parseMagickIndices(spec);
|
|
9693
9721
|
}
|
|
9694
9722
|
stackStep(async (stack, _backend, parents) => {
|
|
9723
|
+
if (token.endsWith("duplicate") && stack.length === 0) throw new Error(`no images found for operation ${token}`);
|
|
9695
9724
|
if (token.endsWith("clone") || token.endsWith("duplicate")) {
|
|
9696
|
-
const source =
|
|
9697
|
-
|
|
9725
|
+
const source = token.endsWith("clone") ? parents.at(-1) ?? stack : stack;
|
|
9726
|
+
const length = source.length;
|
|
9727
|
+
if (token.endsWith("clone") && length === 0) throw new Error(`UnableToCloneImage ${token}`);
|
|
9728
|
+
for (let repeat = 0; repeat < count; repeat++) for (const index of parseMagickIndexSpec(spec, length, "clone")) {
|
|
9698
9729
|
await yieldTurn11(signal);
|
|
9699
9730
|
await stack.push(await source.get(index));
|
|
9700
9731
|
}
|
|
9701
|
-
} else if (token.endsWith("delete")) await stack.remove(parseMagickIndexSpec(spec, stack.length));
|
|
9732
|
+
} else if (token.endsWith("delete")) await stack.remove(parseMagickIndexSpec(spec, stack.length, "delete"));
|
|
9702
9733
|
else if (token === "-reverse") {
|
|
9703
9734
|
for (let n = 0; n < Math.floor(stack.length / 2); n++) {
|
|
9704
9735
|
await yieldTurn11(signal);
|
|
9705
9736
|
await stack.swap(n, stack.length - 1 - n);
|
|
9706
9737
|
}
|
|
9707
9738
|
} else if (token.endsWith("insert")) {
|
|
9708
|
-
const raw = token === "+insert" ? 0 : Number(spec), target = raw < 0 ?
|
|
9739
|
+
const raw = token === "+insert" ? 0 : Number(spec), target = raw < 0 ? stack.length - 1 + raw : raw;
|
|
9740
|
+
if (!Number.isInteger(target) || target < 0 || target >= stack.length || raw < 0 && target === 0) throw new Error(`invalid image index ${token}`);
|
|
9709
9741
|
for (let n = stack.length - 1; n > target; n--) {
|
|
9710
9742
|
await yieldTurn11(signal);
|
|
9711
9743
|
await stack.swap(n, n - 1);
|
|
9712
9744
|
}
|
|
9713
9745
|
} else {
|
|
9714
|
-
const values = (token === "+swap" ? "-2,-1" : spec
|
|
9746
|
+
const values = parseMagickIndices(token === "+swap" ? "-2,-1" : spec, false).flat();
|
|
9715
9747
|
const a = values[0] ?? -2, b = values[1] ?? -1;
|
|
9716
|
-
|
|
9748
|
+
const i1 = a < 0 ? stack.length + a : a, i2 = b < 0 ? stack.length + b : b;
|
|
9749
|
+
if (i1 === i2 || i1 < 0 || i2 < 0 || i1 >= stack.length || i2 >= stack.length) throw new Error(`invalid image index ${token}`);
|
|
9750
|
+
await stack.swap(i1, i2);
|
|
9717
9751
|
}
|
|
9718
9752
|
return stack;
|
|
9719
9753
|
});
|
|
@@ -9743,7 +9777,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9743
9777
|
}
|
|
9744
9778
|
return result;
|
|
9745
9779
|
} else if (token === "-combine") {
|
|
9746
|
-
if (stack.length
|
|
9780
|
+
if (stack.length === 0) return stack;
|
|
9747
9781
|
const sources = [];
|
|
9748
9782
|
for (let index = 0; index < Math.min(4, stack.length); index++) sources.push(await stack.get(index));
|
|
9749
9783
|
const base = sources[0], result = await transformStoredMagickRaster(base, backend, combinePixelSteps(base.width * base.height * 4, sources.map((image) => image.width * image.height * 4)), signal, base, sources);
|
|
@@ -10281,13 +10315,18 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10281
10315
|
return frames;
|
|
10282
10316
|
});
|
|
10283
10317
|
} else if (!operandsOnly && token === "-shave") {
|
|
10284
|
-
const geometry =
|
|
10318
|
+
const geometry = tokens[++i] ?? "0x0", parsed = parseMagickGeometry(geometry);
|
|
10319
|
+
const width = Math.max(0, Math.round(parsed.width ?? 0)), height = Math.max(0, Math.round(parsed.height ?? width));
|
|
10285
10320
|
steps.push(async (image, backend) => {
|
|
10286
10321
|
if (!image) return;
|
|
10287
|
-
|
|
10322
|
+
if (width * 2 >= image.width || height * 2 >= image.height) {
|
|
10323
|
+
analysis.warnings += `magick: geometry does not contain image '${geometry}'
|
|
10324
|
+
`;
|
|
10325
|
+
return image;
|
|
10326
|
+
}
|
|
10288
10327
|
return {
|
|
10289
|
-
...await transformStoredImage2(image, backend.storage, { kind: "extract", left, top, width:
|
|
10290
|
-
virtualCanvas: magickBorderCanvas(image, -
|
|
10328
|
+
...await transformStoredImage2(image, backend.storage, { kind: "extract", left: width, top: height, width: image.width - width * 2, height: image.height - height * 2 }, signal),
|
|
10329
|
+
virtualCanvas: magickBorderCanvas(image, -width, -height)
|
|
10291
10330
|
};
|
|
10292
10331
|
});
|
|
10293
10332
|
} else if (!operandsOnly && token === "-trim") {
|
|
@@ -10301,6 +10340,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10301
10340
|
steps.push(async (image, backend) => {
|
|
10302
10341
|
if (!image) return;
|
|
10303
10342
|
const layout = magickExtentLayout(image, geometry, captured);
|
|
10343
|
+
if (!layout) return image;
|
|
10304
10344
|
const virtualCanvas = magickResizeCanvas(image, layout.width, layout.height);
|
|
10305
10345
|
const source = image[magickInput];
|
|
10306
10346
|
const canvas = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poe-platform/safe-bash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.845",
|
|
4
4
|
"description": "Extensible virtual shell with pluggable filesystems and streaming commands",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1415,7 +1415,7 @@
|
|
|
1415
1415
|
"access": "public"
|
|
1416
1416
|
},
|
|
1417
1417
|
"dependencies": {
|
|
1418
|
-
"@poe-platform/safe-fs": "0.1.
|
|
1418
|
+
"@poe-platform/safe-fs": "0.1.845",
|
|
1419
1419
|
"pdf-lib": "1.17.1",
|
|
1420
1420
|
"@types/node": "^25.2.2",
|
|
1421
1421
|
"@formatjs/intl-numberformat": "9.4.0",
|