pixeli 1.0.4 → 1.0.6-beta.3
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 +17 -0
- package/dist/cli/commands/project/backend/dist/assets/Export-D0AicdAp.js +1 -0
- package/dist/cli/commands/project/backend/dist/assets/Merge-Dz2TnSs6.js +4 -0
- package/dist/cli/commands/project/backend/dist/assets/Toggle-Bw_sGges.js +1 -0
- package/dist/cli/commands/project/backend/dist/assets/index--iLQSLSH.css +1 -0
- package/dist/cli/commands/project/backend/dist/assets/index-7xq0SvzN.js +3 -0
- package/dist/cli/commands/project/backend/dist/assets/views-C-jtlP0g.js +1 -0
- package/dist/cli/commands/project/backend/dist/favicon.ico +0 -0
- package/dist/cli/commands/project/backend/dist/index.html +14 -0
- package/dist/cli/commands/project/backend/index.d.ts +171 -0
- package/dist/cli/commands/project/backend/index.js +28 -0
- package/dist/cli/commands/project/backend/routers/fs.d.ts +61 -0
- package/dist/cli/commands/project/backend/routers/fs.js +40 -0
- package/dist/cli/commands/project/backend/routers/index.d.ts +2 -0
- package/dist/cli/commands/project/backend/routers/index.js +3 -0
- package/dist/cli/commands/project/backend/routers/merge.d.ts +109 -0
- package/dist/cli/commands/project/backend/routers/merge.js +26 -0
- package/dist/cli/commands/project/backend/validators/fs.d.ts +11 -0
- package/dist/cli/commands/project/backend/validators/fs.js +8 -0
- package/dist/cli/commands/project/backend/validators/merge.d.ts +32 -0
- package/dist/cli/commands/project/backend/validators/merge.js +17 -0
- package/dist/cli/commands/project/index.d.ts +2 -0
- package/dist/cli/commands/project/index.js +64 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/schemas/project.d.ts +4 -0
- package/dist/cli/schemas/project.js +5 -0
- package/dist/core/jobs/types.d.ts +2 -2
- package/dist/core/jobs/types.js +1 -1
- package/dist/core/merges/grid/steps/createComposites.js +1 -1
- package/dist/core/merges/masonry/index.d.ts +2 -2
- package/dist/core/merges/masonry/index.js +1 -0
- package/dist/core/merges/masonry/steps/createComposites.js +1 -1
- package/dist/core/merges/shared-steps/exportCanvas.js +2 -1
- package/dist/core/merges/shared-steps/loadImages.js +1 -1
- package/dist/core/merges/types.d.ts +2 -2
- package/dist/core/merges/types.js +1 -1
- package/dist/core/pipeline/mergePipeline.d.ts +5 -5
- package/dist/core/pipeline/mergePipeline.js +1 -1
- package/dist/core/utils/images/addImageBorder.d.ts +2 -2
- package/dist/core/utils/images/addImageBorder.js +1 -1
- package/dist/core/utils/images/getImageHeights.d.ts +2 -2
- package/dist/core/utils/images/getImageHeights.js +1 -1
- package/dist/core/utils/images/getImageWidths.d.ts +2 -2
- package/dist/core/utils/images/getImageWidths.js +1 -1
- package/dist/core/utils/images/getSmallestImageDimensions.d.ts +2 -2
- package/dist/core/utils/images/getSmallestImageDimensions.js +1 -1
- package/dist/core/utils/images/handleImageEdges.d.ts +2 -2
- package/dist/core/utils/images/handleImageEdges.js +1 -1
- package/dist/core/utils/images/isActualImage.d.ts +2 -2
- package/dist/core/utils/images/isActualImage.js +1 -1
- package/dist/core/utils/images/roundImage.d.ts +2 -2
- package/dist/core/utils/images/roundImage.js +1 -1
- package/dist/core/utils/images/roundImages.d.ts +2 -2
- package/dist/core/utils/images/roundImages.js +1 -1
- package/dist/core/utils/images/scaleImage.d.ts +2 -2
- package/dist/core/utils/images/scaleImage.js +2 -2
- package/dist/core/utils/images/scaleImages.d.ts +2 -2
- package/dist/core/utils/images/scaleImages.js +2 -2
- package/package.json +21 -8
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { Hono } from 'hono';
|
|
4
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
5
|
+
import { serve } from '@hono/node-server';
|
|
6
|
+
import * as routers from './routers/index.js';
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const app = new Hono();
|
|
9
|
+
export const serveApp = (projectDir, cb = null, port = null) => {
|
|
10
|
+
// Serve frontend build
|
|
11
|
+
app.use('/*', serveStatic({ root: path.join(__dirname, 'dist') }));
|
|
12
|
+
// Routes
|
|
13
|
+
const routes = app
|
|
14
|
+
.basePath('/api')
|
|
15
|
+
.route('/fs', routers.createFsRouter(projectDir))
|
|
16
|
+
.route('/merge', routers.createMergeRouter(projectDir));
|
|
17
|
+
app.get('*', serveStatic({ path: path.join(__dirname, 'dist/index.html') }));
|
|
18
|
+
// For specific ports (not required during build)
|
|
19
|
+
if (port) {
|
|
20
|
+
serve({
|
|
21
|
+
fetch: app.fetch,
|
|
22
|
+
port,
|
|
23
|
+
}, (info) => (cb ? cb(info) : console.log(`Project running at: http://localhost:${info.port}`)));
|
|
24
|
+
return routes;
|
|
25
|
+
}
|
|
26
|
+
serve(app, (info) => (cb ? cb(info) : console.log(`Project running at: http://localhost:${port}`)));
|
|
27
|
+
return routes;
|
|
28
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export declare const createFsRouter: (projectDir: string) => import("hono/hono-base").HonoBase<import("hono/types").BlankEnv, {
|
|
2
|
+
"/": {
|
|
3
|
+
$get: {
|
|
4
|
+
input: {
|
|
5
|
+
query: {
|
|
6
|
+
recursive: "true" | "false";
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
output: {
|
|
10
|
+
error: string;
|
|
11
|
+
at: string;
|
|
12
|
+
};
|
|
13
|
+
outputFormat: "json";
|
|
14
|
+
status: 400;
|
|
15
|
+
} | {
|
|
16
|
+
input: {
|
|
17
|
+
query: {
|
|
18
|
+
recursive: "true" | "false";
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
output: {
|
|
22
|
+
images: {
|
|
23
|
+
size: number;
|
|
24
|
+
path: string;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}[];
|
|
28
|
+
ignoredPaths: string[];
|
|
29
|
+
};
|
|
30
|
+
outputFormat: "json";
|
|
31
|
+
status: 200;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
} & {
|
|
35
|
+
"/preview": {
|
|
36
|
+
$get: {
|
|
37
|
+
input: {
|
|
38
|
+
query: {
|
|
39
|
+
path: string | string[];
|
|
40
|
+
size?: string | string[];
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
output: {};
|
|
44
|
+
outputFormat: string;
|
|
45
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
46
|
+
} | {
|
|
47
|
+
input: {
|
|
48
|
+
query: {
|
|
49
|
+
path: string | string[];
|
|
50
|
+
size?: string | string[];
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
output: {
|
|
54
|
+
error: string;
|
|
55
|
+
at: string;
|
|
56
|
+
};
|
|
57
|
+
outputFormat: "json";
|
|
58
|
+
status: 400;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}, "/", "/preview">;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import sharp from 'sharp';
|
|
3
|
+
import { Hono } from 'hono';
|
|
4
|
+
import { loadImages } from '../../../../modules/loadImages.js';
|
|
5
|
+
import { zValidator } from '@hono/zod-validator';
|
|
6
|
+
import { fsGetQuerySchema, fsPreviewGetQuerySchema } from '../validators/fs.js';
|
|
7
|
+
export const createFsRouter = (projectDir) => {
|
|
8
|
+
const fsRouter = new Hono()
|
|
9
|
+
// Chaining methods for type inference
|
|
10
|
+
.get('/', zValidator('query', fsGetQuerySchema, (result, c) => {
|
|
11
|
+
if (!result.success) {
|
|
12
|
+
const currentIssue = result.error.issues[0];
|
|
13
|
+
return c.json({ error: currentIssue.message, at: currentIssue.path.join('.') }, 400);
|
|
14
|
+
}
|
|
15
|
+
}), async (c) => {
|
|
16
|
+
const params = c.req.valid('query');
|
|
17
|
+
const { images: buffers, imagePaths, ignoredPaths, } = await loadImages({
|
|
18
|
+
input: { dir: projectDir, files: undefined },
|
|
19
|
+
recursive: params.recursive === 'true',
|
|
20
|
+
});
|
|
21
|
+
const images = buffers.map(async (buff, index) => {
|
|
22
|
+
const { width, height } = await sharp(buff, { limitInputPixels: false }).metadata();
|
|
23
|
+
const relativePath = path.relative(projectDir, imagePaths[index]);
|
|
24
|
+
return { size: buff.length, path: relativePath, width, height };
|
|
25
|
+
});
|
|
26
|
+
return c.json({ images: await Promise.all(images), ignoredPaths }, 200);
|
|
27
|
+
})
|
|
28
|
+
.get('/preview', zValidator('query', fsPreviewGetQuerySchema, (result, c) => {
|
|
29
|
+
if (!result.success) {
|
|
30
|
+
const currentIssue = result.error.issues[0];
|
|
31
|
+
return c.json({ error: currentIssue.message, at: currentIssue.path.join('.') }, 400);
|
|
32
|
+
}
|
|
33
|
+
}), async (c) => {
|
|
34
|
+
const { path: filePath, size } = c.req.valid('query');
|
|
35
|
+
const absolutePath = path.resolve(projectDir, filePath);
|
|
36
|
+
const buffer = await sharp(absolutePath, { limitInputPixels: false }).resize(size).toBuffer();
|
|
37
|
+
return new Response(buffer, { headers: { 'Content-Type': 'image/jpeg' } });
|
|
38
|
+
});
|
|
39
|
+
return fsRouter;
|
|
40
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export declare const createMergeRouter: (projectDir: string) => import("hono/hono-base").HonoBase<import("hono/types").BlankEnv, {
|
|
2
|
+
"/grid": {
|
|
3
|
+
$post: {
|
|
4
|
+
input: {
|
|
5
|
+
json: {
|
|
6
|
+
imagePaths: string[];
|
|
7
|
+
shuffle: boolean;
|
|
8
|
+
gap: number;
|
|
9
|
+
cornerRadius: number;
|
|
10
|
+
canvasColor: {
|
|
11
|
+
r: number;
|
|
12
|
+
g: number;
|
|
13
|
+
b: number;
|
|
14
|
+
alpha: number;
|
|
15
|
+
};
|
|
16
|
+
borderWidth: number;
|
|
17
|
+
borderColor: {
|
|
18
|
+
r: number;
|
|
19
|
+
g: number;
|
|
20
|
+
b: number;
|
|
21
|
+
alpha: number;
|
|
22
|
+
};
|
|
23
|
+
aspectRatio: string;
|
|
24
|
+
imageWidth: number;
|
|
25
|
+
columns: number;
|
|
26
|
+
caption: boolean;
|
|
27
|
+
captions: string[];
|
|
28
|
+
captionColor: {
|
|
29
|
+
r: number;
|
|
30
|
+
g: number;
|
|
31
|
+
b: number;
|
|
32
|
+
alpha: number;
|
|
33
|
+
};
|
|
34
|
+
maxCaptionSize: number;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
output: {};
|
|
38
|
+
outputFormat: string;
|
|
39
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
40
|
+
} | {
|
|
41
|
+
input: {
|
|
42
|
+
json: {
|
|
43
|
+
imagePaths: string[];
|
|
44
|
+
shuffle: boolean;
|
|
45
|
+
gap: number;
|
|
46
|
+
cornerRadius: number;
|
|
47
|
+
canvasColor: {
|
|
48
|
+
r: number;
|
|
49
|
+
g: number;
|
|
50
|
+
b: number;
|
|
51
|
+
alpha: number;
|
|
52
|
+
};
|
|
53
|
+
borderWidth: number;
|
|
54
|
+
borderColor: {
|
|
55
|
+
r: number;
|
|
56
|
+
g: number;
|
|
57
|
+
b: number;
|
|
58
|
+
alpha: number;
|
|
59
|
+
};
|
|
60
|
+
aspectRatio: string;
|
|
61
|
+
imageWidth: number;
|
|
62
|
+
columns: number;
|
|
63
|
+
caption: boolean;
|
|
64
|
+
captions: string[];
|
|
65
|
+
captionColor: {
|
|
66
|
+
r: number;
|
|
67
|
+
g: number;
|
|
68
|
+
b: number;
|
|
69
|
+
alpha: number;
|
|
70
|
+
};
|
|
71
|
+
maxCaptionSize: number;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
output: {
|
|
75
|
+
error: string;
|
|
76
|
+
at: string;
|
|
77
|
+
};
|
|
78
|
+
outputFormat: "json";
|
|
79
|
+
status: 400;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
} & {
|
|
83
|
+
"/masonry": {
|
|
84
|
+
$post: {
|
|
85
|
+
input: {};
|
|
86
|
+
output: {};
|
|
87
|
+
outputFormat: import("hono/types").ResponseFormat;
|
|
88
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
} & {
|
|
92
|
+
collage: {
|
|
93
|
+
$post: {
|
|
94
|
+
input: {};
|
|
95
|
+
output: {};
|
|
96
|
+
outputFormat: import("hono/types").ResponseFormat;
|
|
97
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
} & {
|
|
101
|
+
template: {
|
|
102
|
+
$post: {
|
|
103
|
+
input: {};
|
|
104
|
+
output: {};
|
|
105
|
+
outputFormat: import("hono/types").ResponseFormat;
|
|
106
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
}, "/", "template">;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { mergePostGridSchema } from '../validators/merge.js';
|
|
3
|
+
import { zValidator } from '@hono/zod-validator';
|
|
4
|
+
import { gridMerge } from '../../../../../core/index.js';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
export const createMergeRouter = (projectDir) => {
|
|
7
|
+
const mergeRouter = new Hono()
|
|
8
|
+
// Chaining methods for type inference
|
|
9
|
+
.post('/grid', zValidator('json', mergePostGridSchema, (result, c) => {
|
|
10
|
+
if (!result.success) {
|
|
11
|
+
const currentIssue = result.error.issues[0];
|
|
12
|
+
return c.json({ error: currentIssue.message, at: currentIssue.path.join('.') }, 400);
|
|
13
|
+
}
|
|
14
|
+
}), async (c) => {
|
|
15
|
+
const data = c.req.valid('json');
|
|
16
|
+
const { imagePaths, ...gridMergeOptions } = data;
|
|
17
|
+
const options = { ...gridMergeOptions, format: 'png' };
|
|
18
|
+
const absolutePaths = imagePaths.map((p) => path.resolve(projectDir, p));
|
|
19
|
+
const output = await gridMerge(absolutePaths, options);
|
|
20
|
+
return new Response(output, { headers: { 'Content-Type': 'image/png' } });
|
|
21
|
+
})
|
|
22
|
+
.post('/masonry')
|
|
23
|
+
.post('collage')
|
|
24
|
+
.post('template');
|
|
25
|
+
return mergeRouter;
|
|
26
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export declare const fsGetQuerySchema: z.ZodObject<{
|
|
3
|
+
recursive: z.ZodEnum<{
|
|
4
|
+
true: "true";
|
|
5
|
+
false: "false";
|
|
6
|
+
}>;
|
|
7
|
+
}, z.z.core.$strip>;
|
|
8
|
+
export declare const fsPreviewGetQuerySchema: z.ZodObject<{
|
|
9
|
+
path: z.ZodString;
|
|
10
|
+
size: z.ZodDefault<z.z.ZodCoercedNumber<unknown>>;
|
|
11
|
+
}, z.z.core.$strip>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export declare const mergePostGridSchema: z.ZodObject<{
|
|
3
|
+
imagePaths: z.ZodArray<z.ZodString>;
|
|
4
|
+
shuffle: z.ZodBoolean;
|
|
5
|
+
gap: z.ZodNumber;
|
|
6
|
+
cornerRadius: z.ZodNumber;
|
|
7
|
+
canvasColor: z.ZodObject<{
|
|
8
|
+
r: z.ZodNumber;
|
|
9
|
+
g: z.ZodNumber;
|
|
10
|
+
b: z.ZodNumber;
|
|
11
|
+
alpha: z.ZodNumber;
|
|
12
|
+
}, z.z.core.$strip>;
|
|
13
|
+
borderWidth: z.ZodNumber;
|
|
14
|
+
borderColor: z.ZodObject<{
|
|
15
|
+
r: z.ZodNumber;
|
|
16
|
+
g: z.ZodNumber;
|
|
17
|
+
b: z.ZodNumber;
|
|
18
|
+
alpha: z.ZodNumber;
|
|
19
|
+
}, z.z.core.$strip>;
|
|
20
|
+
aspectRatio: z.ZodString;
|
|
21
|
+
imageWidth: z.ZodNumber;
|
|
22
|
+
columns: z.ZodNumber;
|
|
23
|
+
caption: z.ZodBoolean;
|
|
24
|
+
captions: z.ZodArray<z.ZodString>;
|
|
25
|
+
captionColor: z.ZodObject<{
|
|
26
|
+
r: z.ZodNumber;
|
|
27
|
+
g: z.ZodNumber;
|
|
28
|
+
b: z.ZodNumber;
|
|
29
|
+
alpha: z.ZodNumber;
|
|
30
|
+
}, z.z.core.$strip>;
|
|
31
|
+
maxCaptionSize: z.ZodNumber;
|
|
32
|
+
}, z.z.core.$strip>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export const mergePostGridSchema = z.object({
|
|
3
|
+
imagePaths: z.array(z.string()),
|
|
4
|
+
shuffle: z.boolean(),
|
|
5
|
+
gap: z.number(),
|
|
6
|
+
cornerRadius: z.number(),
|
|
7
|
+
canvasColor: z.object({ r: z.number(), g: z.number(), b: z.number(), alpha: z.number() }),
|
|
8
|
+
borderWidth: z.number(),
|
|
9
|
+
borderColor: z.object({ r: z.number(), g: z.number(), b: z.number(), alpha: z.number() }),
|
|
10
|
+
aspectRatio: z.string(),
|
|
11
|
+
imageWidth: z.number(),
|
|
12
|
+
columns: z.number(),
|
|
13
|
+
caption: z.boolean(),
|
|
14
|
+
captions: z.array(z.string()),
|
|
15
|
+
captionColor: z.object({ r: z.number(), g: z.number(), b: z.number(), alpha: z.number() }),
|
|
16
|
+
maxCaptionSize: z.number(),
|
|
17
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { buildCommandFromSchema } from '../../utils/buildCommandFromSchema.js';
|
|
2
|
+
import { cliProjectSchema } from '../../schemas/project.js';
|
|
3
|
+
import { loadImages } from '../../modules/loadImages.js';
|
|
4
|
+
import { MergeProgressBar } from '../../modules/progressBar.js';
|
|
5
|
+
import { MessageRenderer, MESSAGES } from '../../../core/modules/messages.js';
|
|
6
|
+
import { toErrorMessage } from '../../utils/toErrorMessage.js';
|
|
7
|
+
import { serveApp } from './backend/index.js';
|
|
8
|
+
const projectCommand = buildCommandFromSchema('project', 'Starts a new project in the directory specified', cliProjectSchema, {
|
|
9
|
+
dir: {
|
|
10
|
+
flags: '[directory-path]',
|
|
11
|
+
description: 'Directory to start a new project in, defaults to current working directory',
|
|
12
|
+
},
|
|
13
|
+
}, {}).action(async (dir) => {
|
|
14
|
+
const input = { dir };
|
|
15
|
+
try {
|
|
16
|
+
const { dir: projectDir } = await cliProjectSchema.parseAsync(input);
|
|
17
|
+
serveApp(projectDir, (info) => {
|
|
18
|
+
console.log(`Server running at http://localhost:${info.port}`);
|
|
19
|
+
}, 3000);
|
|
20
|
+
// console.log('xxx');
|
|
21
|
+
// console.log('yyy');
|
|
22
|
+
// console.log(5 + 5);
|
|
23
|
+
// // Use load images module
|
|
24
|
+
// const { images, imagePaths, ignoredPaths } = await loadImages({
|
|
25
|
+
// input: { files: validatedOptions.files, dir: validatedOptions.dir },
|
|
26
|
+
// recursive: validatedOptions.recursive,
|
|
27
|
+
// });
|
|
28
|
+
// // Ensure user knows about ignored files
|
|
29
|
+
// if (ignoredPaths.length) {
|
|
30
|
+
// const warning = new MessageRenderer(MESSAGES.WARNINGS.IGNORED_FILES, ignoredPaths.join('\n') + '\n');
|
|
31
|
+
// const confirmation = await warning.confirm();
|
|
32
|
+
// if (!confirmation) return;
|
|
33
|
+
// }
|
|
34
|
+
// // Collect merge options
|
|
35
|
+
// const { recursive, output, files, dir, ...cliOptions } = validatedOptions;
|
|
36
|
+
// const format = path.extname(output).replace('.', '');
|
|
37
|
+
// const captions = imagePaths.map((p) => path.basename(p));
|
|
38
|
+
// const mergeOptions = {
|
|
39
|
+
// format,
|
|
40
|
+
// captions,
|
|
41
|
+
// ...cliOptions,
|
|
42
|
+
// };
|
|
43
|
+
// // Get grid buffer
|
|
44
|
+
// const buffer = await gridMerge(images, mergeOptions, (progressInfo) => {
|
|
45
|
+
// if (!bar.progressBar.isActive) {
|
|
46
|
+
// bar.startBar(progressInfo.phase);
|
|
47
|
+
// } else {
|
|
48
|
+
// bar.updateBar(progressInfo);
|
|
49
|
+
// }
|
|
50
|
+
// });
|
|
51
|
+
// // Write file and display success message
|
|
52
|
+
// await fs.writeFile(output, buffer);
|
|
53
|
+
// bar.endBar();
|
|
54
|
+
// const success = new MessageRenderer(MESSAGES.SUCCESS.OUTPUT, output);
|
|
55
|
+
// success.render();
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
// Create and render error
|
|
59
|
+
const errorMessage = toErrorMessage(err);
|
|
60
|
+
const error = new MessageRenderer(errorMessage);
|
|
61
|
+
error.render();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
export default projectCommand;
|
package/dist/cli/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import gridCommand from './commands/grid/index.js';
|
|
|
5
5
|
import masonryCommand from './commands/masonry/index.js';
|
|
6
6
|
import templateCommand from './commands/template/index.js';
|
|
7
7
|
import collageCommand from './commands/collage/index.js';
|
|
8
|
+
import projectCommand from './commands/project/index.js';
|
|
8
9
|
import pkg from '../../package.json' with { type: 'json' };
|
|
9
10
|
const program = new Command();
|
|
10
11
|
program
|
|
@@ -15,6 +16,7 @@ program.addCommand(gridCommand);
|
|
|
15
16
|
program.addCommand(masonryCommand);
|
|
16
17
|
program.addCommand(templateCommand);
|
|
17
18
|
program.addCommand(collageCommand);
|
|
19
|
+
program.addCommand(projectCommand);
|
|
18
20
|
configureCommandErrors(program);
|
|
19
21
|
try {
|
|
20
22
|
program.parse();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SharpInput } from 'sharp';
|
|
2
2
|
import type { MergeTypeOptions } from '../merges/types.js';
|
|
3
3
|
export type MergeJob = {
|
|
4
4
|
/** File paths to all of the images to load. */
|
|
5
|
-
inputs:
|
|
5
|
+
inputs: SharpInput[];
|
|
6
6
|
} & MergeTypeOptions;
|
|
7
7
|
export interface BatchOptions {
|
|
8
8
|
/** Throws a `MergeError` instantly and stops the process if true. */
|
package/dist/core/jobs/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import {} from 'sharp';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { requireNonEmptyArray, requireState } from '../../../pipeline/guards.js';
|
|
2
|
-
import
|
|
2
|
+
import {} from 'sharp';
|
|
3
3
|
import { createSvgTextBuffer } from '../../../utils/svg/createSvgTextBuffer.js';
|
|
4
4
|
import { rgbaToHex } from '../../../utils/colors/rgbaToHex.js';
|
|
5
5
|
export const createComposites = async (context, options, onProgress) => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { MasonryMerge } from '../types.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type Sharp } from 'sharp';
|
|
3
3
|
export interface MasonryState {
|
|
4
4
|
rowHeight: number;
|
|
5
5
|
columnWidth: number;
|
|
6
6
|
canvasWidth: number;
|
|
7
7
|
canvasHeight: number;
|
|
8
|
-
lanes:
|
|
8
|
+
lanes: Sharp[][];
|
|
9
9
|
}
|
|
10
10
|
export declare const masonryMerge: MasonryMerge;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MergePipeline } from '../../pipeline/mergePipeline.js';
|
|
2
2
|
import { masonrySchema } from '../../schemas/masonry.js';
|
|
3
|
+
import {} from 'sharp';
|
|
3
4
|
import { loadImages } from '../shared-steps/loadImages.js';
|
|
4
5
|
import { createCanvas } from '../shared-steps/createCanvas.js';
|
|
5
6
|
import { applyComposites } from '../shared-steps/applyComposites.js';
|
|
@@ -5,7 +5,8 @@ export const exportCanvas = async (context, options, _onProgress) => {
|
|
|
5
5
|
// Ensure canvas exists
|
|
6
6
|
requireContextProp(context, 'canvas');
|
|
7
7
|
try {
|
|
8
|
-
|
|
8
|
+
const format = options.format === 'jpg' ? 'jpeg' : options.format;
|
|
9
|
+
return await context.canvas.toFormat(format).toBuffer();
|
|
9
10
|
}
|
|
10
11
|
catch (err) {
|
|
11
12
|
// Assuming ALL sharp errors are instances of the Error object
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { SharpInput } from 'sharp';
|
|
2
2
|
import type { Color } from '../utils/colors/types.js';
|
|
3
3
|
import type { Template } from './template/types.js';
|
|
4
4
|
export interface ProgressInfo {
|
|
@@ -20,7 +20,7 @@ export type OnProgress = (info: ProgressInfo) => void;
|
|
|
20
20
|
* @returns A Promise resolving to the merged image buffer
|
|
21
21
|
*/
|
|
22
22
|
interface MergeCommand<T> {
|
|
23
|
-
(imageInputs:
|
|
23
|
+
(imageInputs: SharpInput[], options: T, onProgress?: OnProgress): Promise<Buffer>;
|
|
24
24
|
}
|
|
25
25
|
interface BaseMergeOptions {
|
|
26
26
|
/** Whether to randomize image order before merging. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Sharp, type SharpInput, type OverlayOptions } from 'sharp';
|
|
2
2
|
import type z from 'zod';
|
|
3
3
|
import type { OnProgress, ProgressInfo } from '../merges/types.js';
|
|
4
4
|
export interface MergeContext<TState> {
|
|
5
|
-
inputs:
|
|
5
|
+
inputs: SharpInput[];
|
|
6
6
|
progressInfo: ProgressInfo;
|
|
7
|
-
images:
|
|
8
|
-
canvas?:
|
|
9
|
-
composites:
|
|
7
|
+
images: Sharp[];
|
|
8
|
+
canvas?: Sharp;
|
|
9
|
+
composites: OverlayOptions[];
|
|
10
10
|
captions: string[];
|
|
11
11
|
state: TState;
|
|
12
12
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Sharp } from 'sharp';
|
|
2
2
|
import type { RGBA } from '../colors/types.js';
|
|
3
3
|
interface Options {
|
|
4
4
|
borderWidth: number;
|
|
@@ -9,5 +9,5 @@ interface Options {
|
|
|
9
9
|
imageHeight: number;
|
|
10
10
|
finalizePipeline?: boolean;
|
|
11
11
|
}
|
|
12
|
-
export declare const addImageBorder: (image:
|
|
12
|
+
export declare const addImageBorder: (image: Sharp, { borderWidth, borderHeight, borderColor, imageWidth, imageHeight, cornerRadius, finalizePipeline }: Options) => Promise<Sharp>;
|
|
13
13
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import sharp from 'sharp';
|
|
1
|
+
import sharp, {} from 'sharp';
|
|
2
2
|
export const addImageBorder = async (image, { borderWidth, borderHeight, borderColor, imageWidth, imageHeight, cornerRadius = 0, finalizePipeline = false }) => {
|
|
3
3
|
// Only add borders to an image if needed
|
|
4
4
|
if (borderWidth <= 0)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare const getImageHeights: (images:
|
|
1
|
+
import { type Sharp } from 'sharp';
|
|
2
|
+
export declare const getImageHeights: (images: Sharp[]) => Promise<number[]>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare const getImageWidths: (images:
|
|
1
|
+
import { type Sharp } from 'sharp';
|
|
2
|
+
export declare const getImageWidths: (images: Sharp[]) => Promise<number[]>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare const getSmallestImageDimensions: (images:
|
|
1
|
+
import { type Sharp } from 'sharp';
|
|
2
|
+
export declare const getSmallestImageDimensions: (images: Sharp[]) => Promise<{
|
|
3
3
|
smallestWidth: number;
|
|
4
4
|
smallestHeight: number;
|
|
5
5
|
}>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type Sharp } from 'sharp';
|
|
2
2
|
import type { RGBA } from '../colors/types.js';
|
|
3
3
|
interface Options {
|
|
4
4
|
borderWidth: number;
|
|
@@ -9,5 +9,5 @@ interface Options {
|
|
|
9
9
|
imageHeight: number;
|
|
10
10
|
finalizePipeline?: boolean;
|
|
11
11
|
}
|
|
12
|
-
export declare const handleImageEdges: (image:
|
|
12
|
+
export declare const handleImageEdges: (image: Sharp, { borderWidth, borderHeight, borderColor, imageWidth, imageHeight, cornerRadius, finalizePipeline }: Options) => Promise<Sharp>;
|
|
13
13
|
export {};
|