pi-image-tools 1.3.0 → 1.4.0
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/CHANGELOG.md +135 -115
- package/README.md +16 -8
- package/package.json +13 -4
- package/src/clipboard.ts +99 -89
- package/src/config.ts +5 -2
- package/src/debug-logger.ts +4 -2
- package/src/image-preview.ts +25 -32
- package/src/image-size.ts +62 -63
- package/src/image-transcode.ts +206 -0
- package/src/index.ts +23 -27
- package/src/inline-user-preview.ts +512 -523
- package/src/keybindings.ts +52 -50
- package/src/powershell.ts +82 -56
- package/src/preview-logging.ts +28 -0
- package/src/providers/command-runner.ts +86 -68
- package/src/providers/mac-osascript-pngf.ts +17 -56
- package/src/providers/mac-osascript-publicpng.ts +16 -55
- package/src/providers/mac-pngpaste.ts +16 -55
- package/src/providers/native-module.ts +84 -84
- package/src/providers/powershell-forms.ts +87 -95
- package/src/providers/provider-helpers.ts +196 -0
- package/src/providers/registry.ts +88 -88
- package/src/providers/types.ts +24 -24
- package/src/providers/wl-paste.ts +21 -56
- package/src/providers/xclip.ts +21 -57
- package/src/recent-images.ts +55 -83
- package/src/shell-environment.ts +75 -75
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
defaultCommandRunner,
|
|
4
|
-
MAX_BUFFER_BYTES,
|
|
5
|
-
READ_TIMEOUT_MS,
|
|
6
|
-
type CommandRunner,
|
|
7
|
-
} from "./command-runner.js";
|
|
8
|
-
import type { ClipboardImageProvider, ClipboardProviderContext, ClipboardReadResult } from "./types.js";
|
|
1
|
+
import { NamespacedCommandProvider, providerImageResult, type ClipboardReadResult, type CommandExists, type CommandResult, type CommandRunner } from "./provider-helpers.js";
|
|
9
2
|
|
|
10
3
|
const PUBLIC_PNG_SCRIPT = `ObjC.import('AppKit');
|
|
11
4
|
const pasteboard = $.NSPasteboard.generalPasteboard;
|
|
@@ -21,57 +14,25 @@ export interface OsascriptPublicPngProviderOptions {
|
|
|
21
14
|
commandExists?: CommandExists;
|
|
22
15
|
}
|
|
23
16
|
|
|
24
|
-
export class OsascriptPublicPngProvider
|
|
25
|
-
readonly capabilities;
|
|
26
|
-
private readonly commandRunner: CommandRunner;
|
|
27
|
-
private readonly commandExists: CommandExists;
|
|
28
|
-
|
|
17
|
+
export class OsascriptPublicPngProvider extends NamespacedCommandProvider {
|
|
29
18
|
constructor(options: OsascriptPublicPngProviderOptions = {}) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.commandExists = options.commandExists ?? defaultCommandExists;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
isAvailable(context: ClipboardProviderContext): boolean {
|
|
41
|
-
try {
|
|
42
|
-
return this.commandExists("osascript", context);
|
|
43
|
-
} catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
read(context: ClipboardProviderContext): ClipboardReadResult {
|
|
49
|
-
const wrapped = buildNamespaceWrappedCommand(
|
|
19
|
+
super(
|
|
20
|
+
{
|
|
21
|
+
id: "mac-osascript-public-png",
|
|
22
|
+
name: "osascript public.png",
|
|
23
|
+
platforms: ["darwin"],
|
|
24
|
+
priority: options.priority ?? 20,
|
|
25
|
+
},
|
|
50
26
|
"osascript",
|
|
51
|
-
|
|
52
|
-
context,
|
|
53
|
-
this.commandExists,
|
|
27
|
+
options,
|
|
54
28
|
);
|
|
55
|
-
|
|
56
|
-
environment: context.environment,
|
|
57
|
-
maxBuffer: MAX_BUFFER_BYTES,
|
|
58
|
-
timeout: READ_TIMEOUT_MS,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
if (result.missingCommand) {
|
|
62
|
-
return { available: false, image: null };
|
|
63
|
-
}
|
|
29
|
+
}
|
|
64
30
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
31
|
+
protected buildArgs(): readonly string[] {
|
|
32
|
+
return ["-l", "JavaScript", "-e", PUBLIC_PNG_SCRIPT];
|
|
33
|
+
}
|
|
68
34
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
image: {
|
|
72
|
-
bytes: new Uint8Array(result.stdout),
|
|
73
|
-
mimeType: "image/png",
|
|
74
|
-
},
|
|
75
|
-
};
|
|
35
|
+
protected readFromResult(result: CommandResult): ClipboardReadResult {
|
|
36
|
+
return providerImageResult(new Uint8Array(result.stdout), "image/png");
|
|
76
37
|
}
|
|
77
38
|
}
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
defaultCommandRunner,
|
|
4
|
-
MAX_BUFFER_BYTES,
|
|
5
|
-
READ_TIMEOUT_MS,
|
|
6
|
-
type CommandRunner,
|
|
7
|
-
} from "./command-runner.js";
|
|
8
|
-
import type { ClipboardImageProvider, ClipboardProviderContext, ClipboardReadResult } from "./types.js";
|
|
1
|
+
import { NamespacedCommandProvider, providerImageResult, type ClipboardReadResult, type CommandExists, type CommandResult, type CommandRunner } from "./provider-helpers.js";
|
|
9
2
|
|
|
10
3
|
export interface PngpasteProviderOptions {
|
|
11
4
|
priority?: number;
|
|
@@ -13,57 +6,25 @@ export interface PngpasteProviderOptions {
|
|
|
13
6
|
commandExists?: CommandExists;
|
|
14
7
|
}
|
|
15
8
|
|
|
16
|
-
export class PngpasteProvider
|
|
17
|
-
readonly capabilities;
|
|
18
|
-
private readonly commandRunner: CommandRunner;
|
|
19
|
-
private readonly commandExists: CommandExists;
|
|
20
|
-
|
|
9
|
+
export class PngpasteProvider extends NamespacedCommandProvider {
|
|
21
10
|
constructor(options: PngpasteProviderOptions = {}) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.commandExists = options.commandExists ?? defaultCommandExists;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
isAvailable(context: ClipboardProviderContext): boolean {
|
|
33
|
-
try {
|
|
34
|
-
return this.commandExists("pngpaste", context);
|
|
35
|
-
} catch {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
read(context: ClipboardProviderContext): ClipboardReadResult {
|
|
41
|
-
const wrapped = buildNamespaceWrappedCommand(
|
|
11
|
+
super(
|
|
12
|
+
{
|
|
13
|
+
id: "mac-pngpaste",
|
|
14
|
+
name: "pngpaste",
|
|
15
|
+
platforms: ["darwin"],
|
|
16
|
+
priority: options.priority ?? 10,
|
|
17
|
+
},
|
|
42
18
|
"pngpaste",
|
|
43
|
-
|
|
44
|
-
context,
|
|
45
|
-
this.commandExists,
|
|
19
|
+
options,
|
|
46
20
|
);
|
|
47
|
-
|
|
48
|
-
environment: context.environment,
|
|
49
|
-
maxBuffer: MAX_BUFFER_BYTES,
|
|
50
|
-
timeout: READ_TIMEOUT_MS,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
if (result.missingCommand) {
|
|
54
|
-
return { available: false, image: null };
|
|
55
|
-
}
|
|
21
|
+
}
|
|
56
22
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
23
|
+
protected buildArgs(): readonly string[] {
|
|
24
|
+
return ["-"];
|
|
25
|
+
}
|
|
60
26
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
image: {
|
|
64
|
-
bytes: new Uint8Array(result.stdout),
|
|
65
|
-
mimeType: "image/png",
|
|
66
|
-
},
|
|
67
|
-
};
|
|
27
|
+
protected readFromResult(result: CommandResult): ClipboardReadResult {
|
|
28
|
+
return providerImageResult(new Uint8Array(result.stdout), "image/png");
|
|
68
29
|
}
|
|
69
30
|
}
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
|
|
3
|
-
import { hasGraphicalSession } from "../shell-environment.js";
|
|
4
|
-
import type { ClipboardImageProvider, ClipboardProviderContext, ClipboardReadResult } from "./types.js";
|
|
5
|
-
import type { ClipboardModule } from "../types.js";
|
|
6
|
-
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
let cachedClipboardModule: ClipboardModule | null | undefined;
|
|
9
|
-
|
|
10
|
-
export type ClipboardModuleLoader = (
|
|
11
|
-
platform: NodeJS.Platform,
|
|
12
|
-
environment: NodeJS.ProcessEnv,
|
|
13
|
-
) => ClipboardModule | null;
|
|
14
|
-
|
|
15
|
-
export function loadClipboardModule(
|
|
16
|
-
platform: NodeJS.Platform = process.platform,
|
|
17
|
-
environment: NodeJS.ProcessEnv = process.env,
|
|
18
|
-
): ClipboardModule | null {
|
|
19
|
-
if (cachedClipboardModule !== undefined) {
|
|
20
|
-
return cachedClipboardModule;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (environment.TERMUX_VERSION || !hasGraphicalSession(platform, environment)) {
|
|
24
|
-
cachedClipboardModule = null;
|
|
25
|
-
return cachedClipboardModule;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
cachedClipboardModule = require("@mariozechner/clipboard") as ClipboardModule;
|
|
30
|
-
} catch {
|
|
31
|
-
cachedClipboardModule = null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return cachedClipboardModule;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface NativeModuleProviderOptions {
|
|
38
|
-
priority?: number;
|
|
39
|
-
moduleLoader?: ClipboardModuleLoader;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export class NativeModuleProvider implements ClipboardImageProvider {
|
|
43
|
-
readonly capabilities;
|
|
44
|
-
private readonly moduleLoader: ClipboardModuleLoader;
|
|
45
|
-
|
|
46
|
-
constructor(options: NativeModuleProviderOptions = {}) {
|
|
47
|
-
this.capabilities = {
|
|
48
|
-
id: "native-module",
|
|
49
|
-
name: "@mariozechner/clipboard",
|
|
50
|
-
platforms: "*" as const,
|
|
51
|
-
priority: options.priority ?? 100,
|
|
52
|
-
};
|
|
53
|
-
this.moduleLoader = options.moduleLoader ?? loadClipboardModule;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
isAvailable(context: ClipboardProviderContext): boolean {
|
|
57
|
-
return this.moduleLoader(context.platform, context.environment) !== null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async read(context: ClipboardProviderContext): Promise<ClipboardReadResult> {
|
|
61
|
-
const clipboard = this.moduleLoader(context.platform, context.environment);
|
|
62
|
-
if (!clipboard) {
|
|
63
|
-
return { available: false, image: null };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!clipboard.hasImage()) {
|
|
67
|
-
return { available: true, image: null };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const imageData = await clipboard.getImageBinary();
|
|
71
|
-
if (!imageData || imageData.length === 0) {
|
|
72
|
-
return { available: true, image: null };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const bytes = imageData instanceof Uint8Array ? imageData : Uint8Array.from(imageData);
|
|
76
|
-
return {
|
|
77
|
-
available: true,
|
|
78
|
-
image: {
|
|
79
|
-
bytes,
|
|
80
|
-
mimeType: "image/png",
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
import { hasGraphicalSession } from "../shell-environment.js";
|
|
4
|
+
import type { ClipboardImageProvider, ClipboardProviderContext, ClipboardReadResult } from "./types.js";
|
|
5
|
+
import type { ClipboardModule } from "../types.js";
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
let cachedClipboardModule: ClipboardModule | null | undefined;
|
|
9
|
+
|
|
10
|
+
export type ClipboardModuleLoader = (
|
|
11
|
+
platform: NodeJS.Platform,
|
|
12
|
+
environment: NodeJS.ProcessEnv,
|
|
13
|
+
) => ClipboardModule | null;
|
|
14
|
+
|
|
15
|
+
export function loadClipboardModule(
|
|
16
|
+
platform: NodeJS.Platform = process.platform,
|
|
17
|
+
environment: NodeJS.ProcessEnv = process.env,
|
|
18
|
+
): ClipboardModule | null {
|
|
19
|
+
if (cachedClipboardModule !== undefined) {
|
|
20
|
+
return cachedClipboardModule;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (environment.TERMUX_VERSION || !hasGraphicalSession(platform, environment)) {
|
|
24
|
+
cachedClipboardModule = null;
|
|
25
|
+
return cachedClipboardModule;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
cachedClipboardModule = require("@mariozechner/clipboard") as ClipboardModule;
|
|
30
|
+
} catch {
|
|
31
|
+
cachedClipboardModule = null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return cachedClipboardModule;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface NativeModuleProviderOptions {
|
|
38
|
+
priority?: number;
|
|
39
|
+
moduleLoader?: ClipboardModuleLoader;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class NativeModuleProvider implements ClipboardImageProvider {
|
|
43
|
+
readonly capabilities;
|
|
44
|
+
private readonly moduleLoader: ClipboardModuleLoader;
|
|
45
|
+
|
|
46
|
+
constructor(options: NativeModuleProviderOptions = {}) {
|
|
47
|
+
this.capabilities = {
|
|
48
|
+
id: "native-module",
|
|
49
|
+
name: "@mariozechner/clipboard",
|
|
50
|
+
platforms: "*" as const,
|
|
51
|
+
priority: options.priority ?? 100,
|
|
52
|
+
};
|
|
53
|
+
this.moduleLoader = options.moduleLoader ?? loadClipboardModule;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
isAvailable(context: ClipboardProviderContext): boolean {
|
|
57
|
+
return this.moduleLoader(context.platform, context.environment) !== null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async read(context: ClipboardProviderContext): Promise<ClipboardReadResult> {
|
|
61
|
+
const clipboard = this.moduleLoader(context.platform, context.environment);
|
|
62
|
+
if (!clipboard) {
|
|
63
|
+
return { available: false, image: null };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!clipboard.hasImage()) {
|
|
67
|
+
return { available: true, image: null };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const imageData = await clipboard.getImageBinary();
|
|
71
|
+
if (!imageData || imageData.length === 0) {
|
|
72
|
+
return { available: true, image: null };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const bytes = imageData instanceof Uint8Array ? imageData : Uint8Array.from(imageData);
|
|
76
|
+
return {
|
|
77
|
+
available: true,
|
|
78
|
+
image: {
|
|
79
|
+
bytes,
|
|
80
|
+
mimeType: "image/png",
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,95 +1,87 @@
|
|
|
1
|
-
import { runPowerShellCommand, type PowerShellCommandResult, type RunPowerShellCommandOptions } from "../powershell.js";
|
|
2
|
-
import { MAX_BUFFER_BYTES, READ_TIMEOUT_MS } from "./command-runner.js";
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Add-Type -AssemblyName System.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[System.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
$
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
mimeType: "image/png",
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
} catch {
|
|
92
|
-
return { available: true, image: null };
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
1
|
+
import { runPowerShellCommand, type PowerShellCommandResult, type RunPowerShellCommandOptions } from "../powershell.js";
|
|
2
|
+
import { MAX_BUFFER_BYTES, READ_TIMEOUT_MS } from "./command-runner.js";
|
|
3
|
+
import { mapProviderReadFallback, providerEmptyImage, providerImageResult } from "./provider-helpers.js";
|
|
4
|
+
import type { ClipboardImageProvider, ClipboardProviderContext, ClipboardReadResult } from "./types.js";
|
|
5
|
+
|
|
6
|
+
export type PowerShellRunner = (
|
|
7
|
+
script: string,
|
|
8
|
+
options: RunPowerShellCommandOptions,
|
|
9
|
+
) => PowerShellCommandResult;
|
|
10
|
+
|
|
11
|
+
export interface PowerShellFormsProviderOptions {
|
|
12
|
+
priority?: number;
|
|
13
|
+
powerShellRunner?: PowerShellRunner;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const READ_IMAGE_SCRIPT = `
|
|
17
|
+
$ErrorActionPreference = 'Stop'
|
|
18
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
19
|
+
Add-Type -AssemblyName System.Drawing
|
|
20
|
+
|
|
21
|
+
if (-not [System.Windows.Forms.Clipboard]::ContainsImage()) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
$image = [System.Windows.Forms.Clipboard]::GetImage()
|
|
26
|
+
if ($null -eq $image) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
$stream = New-Object System.IO.MemoryStream
|
|
31
|
+
try {
|
|
32
|
+
$image.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
33
|
+
[System.Convert]::ToBase64String($stream.ToArray())
|
|
34
|
+
} finally {
|
|
35
|
+
$stream.Dispose()
|
|
36
|
+
$image.Dispose()
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
export class PowerShellFormsProvider implements ClipboardImageProvider {
|
|
41
|
+
readonly capabilities;
|
|
42
|
+
private readonly powerShellRunner: PowerShellRunner;
|
|
43
|
+
|
|
44
|
+
constructor(options: PowerShellFormsProviderOptions = {}) {
|
|
45
|
+
this.capabilities = {
|
|
46
|
+
id: "powershell-forms",
|
|
47
|
+
name: "Windows PowerShell Forms clipboard",
|
|
48
|
+
platforms: ["win32"],
|
|
49
|
+
priority: options.priority ?? 20,
|
|
50
|
+
};
|
|
51
|
+
this.powerShellRunner = options.powerShellRunner ?? runPowerShellCommand;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
isAvailable(_context: ClipboardProviderContext): boolean {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
read(_context: ClipboardProviderContext): ClipboardReadResult {
|
|
59
|
+
const result = this.powerShellRunner(READ_IMAGE_SCRIPT, {
|
|
60
|
+
encoded: true,
|
|
61
|
+
maxBuffer: MAX_BUFFER_BYTES,
|
|
62
|
+
sta: true,
|
|
63
|
+
timeout: READ_TIMEOUT_MS,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const fallback = mapProviderReadFallback(result, false);
|
|
67
|
+
if (fallback) {
|
|
68
|
+
return fallback;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const base64 = result.stdout.trim();
|
|
72
|
+
if (!base64) {
|
|
73
|
+
return providerEmptyImage();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const bytes = Buffer.from(base64, "base64");
|
|
78
|
+
if (bytes.length === 0) {
|
|
79
|
+
return providerEmptyImage();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return providerImageResult(new Uint8Array(bytes), "image/png");
|
|
83
|
+
} catch {
|
|
84
|
+
return providerEmptyImage();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|