pixeli 0.1.8 → 1.0.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.
Files changed (204) hide show
  1. package/README.md +341 -88
  2. package/dist/cli/commands/collage/index.d.ts +2 -0
  3. package/dist/cli/commands/collage/index.js +125 -0
  4. package/dist/cli/commands/grid/index.d.ts +2 -0
  5. package/dist/cli/commands/grid/index.js +127 -0
  6. package/dist/cli/commands/masonry/index.d.ts +2 -0
  7. package/dist/cli/commands/masonry/index.js +129 -0
  8. package/dist/cli/commands/template/index.d.ts +2 -0
  9. package/dist/cli/commands/template/index.js +123 -0
  10. package/dist/cli/commands/template/presets/artGallery.d.ts +15 -0
  11. package/dist/cli/commands/template/presets/artGallery.js +15 -0
  12. package/dist/cli/commands/template/presets/dashboardShot.d.ts +15 -0
  13. package/dist/cli/commands/template/presets/dashboardShot.js +16 -0
  14. package/dist/cli/commands/template/presets/horizontalBookSpread.d.ts +15 -0
  15. package/dist/cli/commands/template/presets/horizontalBookSpread.js +13 -0
  16. package/dist/cli/commands/template/presets/instagramGrid.d.ts +15 -0
  17. package/dist/cli/commands/template/presets/instagramGrid.js +16 -0
  18. package/dist/cli/commands/template/presets/verticalBookSpread.d.ts +15 -0
  19. package/dist/cli/commands/template/presets/verticalBookSpread.js +13 -0
  20. package/dist/cli/commands/template/presets.d.ts +73 -0
  21. package/{lib/merges/collage-merge → dist/cli/commands/template}/presets.js +6 -8
  22. package/dist/cli/index.d.ts +2 -0
  23. package/dist/cli/index.js +24 -0
  24. package/dist/cli/modules/loadImages.d.ts +15 -0
  25. package/dist/cli/modules/loadImages.js +74 -0
  26. package/dist/cli/modules/progressBar.d.ts +10 -0
  27. package/dist/cli/modules/progressBar.js +34 -0
  28. package/dist/cli/schemas/collage.d.ts +29 -0
  29. package/dist/cli/schemas/collage.js +38 -0
  30. package/dist/cli/schemas/grid.d.ts +34 -0
  31. package/dist/cli/schemas/grid.js +38 -0
  32. package/dist/cli/schemas/masonry.d.ts +62 -0
  33. package/dist/cli/schemas/masonry.js +62 -0
  34. package/dist/cli/schemas/template.d.ts +31 -0
  35. package/dist/cli/schemas/template.js +49 -0
  36. package/dist/cli/utils/buildCommandFromSchema.d.ts +8 -0
  37. package/dist/cli/utils/buildCommandFromSchema.js +55 -0
  38. package/dist/cli/utils/configureCommandErrors.d.ts +2 -0
  39. package/dist/cli/utils/configureCommandErrors.js +22 -0
  40. package/dist/cli/utils/stringFormatter.d.ts +1 -0
  41. package/dist/cli/utils/stringFormatter.js +3 -0
  42. package/dist/cli/utils/toErrorMessage.d.ts +4 -0
  43. package/dist/cli/utils/toErrorMessage.js +22 -0
  44. package/dist/core/helpers.d.ts +10 -0
  45. package/dist/core/helpers.js +42 -0
  46. package/dist/core/index.d.ts +1 -0
  47. package/dist/core/index.js +1 -0
  48. package/dist/core/mergeError.d.ts +9 -0
  49. package/dist/core/mergeError.js +10 -0
  50. package/dist/core/merges/collage/index.d.ts +9 -0
  51. package/dist/core/merges/collage/index.js +32 -0
  52. package/dist/core/merges/collage/steps/calculateImageDimensions.d.ts +12 -0
  53. package/dist/core/merges/collage/steps/calculateImageDimensions.js +18 -0
  54. package/dist/core/merges/collage/steps/createComposites.d.ts +8 -0
  55. package/dist/core/merges/collage/steps/createComposites.js +58 -0
  56. package/dist/core/merges/collage/steps/resizeAndBorderImages.d.ts +12 -0
  57. package/dist/core/merges/collage/steps/resizeAndBorderImages.js +26 -0
  58. package/dist/core/merges/collage/steps/rotateImages.d.ts +7 -0
  59. package/dist/core/merges/collage/steps/rotateImages.js +9 -0
  60. package/dist/core/merges/grid/index.d.ts +12 -0
  61. package/dist/core/merges/grid/index.js +36 -0
  62. package/dist/core/merges/grid/steps/calculateCanvasDimensions.d.ts +8 -0
  63. package/dist/core/merges/grid/steps/calculateCanvasDimensions.js +18 -0
  64. package/dist/core/merges/grid/steps/calculateFontSize.d.ts +7 -0
  65. package/dist/core/merges/grid/steps/calculateFontSize.js +19 -0
  66. package/dist/core/merges/grid/steps/calculateImageDimensions.d.ts +8 -0
  67. package/dist/core/merges/grid/steps/calculateImageDimensions.js +18 -0
  68. package/dist/core/merges/grid/steps/createComposites.d.ts +10 -0
  69. package/dist/core/merges/grid/steps/createComposites.js +63 -0
  70. package/dist/core/merges/grid/steps/prepareImages.d.ts +10 -0
  71. package/dist/core/merges/grid/steps/prepareImages.js +29 -0
  72. package/dist/core/merges/grid/steps/shuffleImagesAndCaptions.d.ts +7 -0
  73. package/dist/core/merges/grid/steps/shuffleImagesAndCaptions.js +17 -0
  74. package/dist/core/merges/index.d.ts +3 -0
  75. package/dist/core/merges/index.js +3 -0
  76. package/dist/core/merges/masonry/index.d.ts +10 -0
  77. package/dist/core/merges/masonry/index.js +32 -0
  78. package/dist/core/merges/masonry/steps/calculateCanvasDimensions.d.ts +15 -0
  79. package/dist/core/merges/masonry/steps/calculateCanvasDimensions.js +17 -0
  80. package/dist/core/merges/masonry/steps/calculateLaneSize.d.ts +9 -0
  81. package/dist/core/merges/masonry/steps/calculateLaneSize.js +27 -0
  82. package/dist/core/merges/masonry/steps/createComposites.d.ts +25 -0
  83. package/dist/core/merges/masonry/steps/createComposites.js +108 -0
  84. package/dist/core/merges/masonry/steps/resizeImages.d.ts +7 -0
  85. package/dist/core/merges/masonry/steps/resizeImages.js +14 -0
  86. package/dist/core/merges/masonry/steps/splitIntoLanes.d.ts +17 -0
  87. package/dist/core/merges/masonry/steps/splitIntoLanes.js +78 -0
  88. package/dist/core/merges/shared-steps/applyComposites.d.ts +2 -0
  89. package/dist/core/merges/shared-steps/applyComposites.js +16 -0
  90. package/dist/core/merges/shared-steps/createCanvas.d.ts +11 -0
  91. package/dist/core/merges/shared-steps/createCanvas.js +17 -0
  92. package/dist/core/merges/shared-steps/exportCanvas.d.ts +7 -0
  93. package/dist/core/merges/shared-steps/exportCanvas.js +25 -0
  94. package/dist/core/merges/shared-steps/finalizeImagePipelines.d.ts +2 -0
  95. package/dist/core/merges/shared-steps/finalizeImagePipelines.js +9 -0
  96. package/dist/core/merges/shared-steps/loadImages.d.ts +2 -0
  97. package/dist/core/merges/shared-steps/loadImages.js +26 -0
  98. package/dist/core/merges/shared-steps/validateCaptions.d.ts +10 -0
  99. package/dist/core/merges/shared-steps/validateCaptions.js +17 -0
  100. package/dist/core/merges/template/index.d.ts +10 -0
  101. package/dist/core/merges/template/index.js +28 -0
  102. package/dist/core/merges/template/steps/calculateSlotDimensions.d.ts +9 -0
  103. package/dist/core/merges/template/steps/calculateSlotDimensions.js +12 -0
  104. package/dist/core/merges/template/steps/createComposites.d.ts +10 -0
  105. package/dist/core/merges/template/steps/createComposites.js +25 -0
  106. package/dist/core/merges/template/steps/getBlocks.d.ts +13 -0
  107. package/dist/core/merges/template/steps/getBlocks.js +28 -0
  108. package/dist/core/merges/template/types.d.ts +21 -0
  109. package/dist/core/merges/template/types.js +1 -0
  110. package/dist/core/merges/types.d.ts +102 -0
  111. package/dist/core/merges/types.js +1 -0
  112. package/dist/core/modules/messages.d.ts +32 -0
  113. package/dist/core/modules/messages.js +54 -0
  114. package/dist/core/pipeline/guards.d.ts +4 -0
  115. package/dist/core/pipeline/guards.js +23 -0
  116. package/dist/core/pipeline/mergePipeline.d.ts +60 -0
  117. package/dist/core/pipeline/mergePipeline.js +122 -0
  118. package/dist/core/schemas/collage.d.ts +26 -0
  119. package/dist/core/schemas/collage.js +17 -0
  120. package/dist/core/schemas/grid.d.ts +32 -0
  121. package/dist/core/schemas/grid.js +29 -0
  122. package/dist/core/schemas/masonry.d.ts +56 -0
  123. package/dist/core/schemas/masonry.js +43 -0
  124. package/dist/core/schemas/template.d.ts +34 -0
  125. package/dist/core/schemas/template.js +88 -0
  126. package/dist/core/utils/colors/hexToRgba.d.ts +2 -0
  127. package/dist/core/utils/colors/hexToRgba.js +25 -0
  128. package/dist/core/utils/colors/rgbaToHex.d.ts +2 -0
  129. package/dist/core/utils/colors/rgbaToHex.js +15 -0
  130. package/dist/core/utils/colors/types.d.ts +7 -0
  131. package/dist/core/utils/colors/types.js +1 -0
  132. package/dist/core/utils/fonts/getFontSize.d.ts +9 -0
  133. package/dist/core/utils/fonts/getFontSize.js +40 -0
  134. package/dist/core/utils/images/addImageBorder.d.ts +13 -0
  135. package/dist/core/utils/images/addImageBorder.js +33 -0
  136. package/dist/core/utils/images/getImageHeights.d.ts +2 -0
  137. package/dist/core/utils/images/getImageHeights.js +9 -0
  138. package/dist/core/utils/images/getImageWidths.d.ts +2 -0
  139. package/dist/core/utils/images/getImageWidths.js +9 -0
  140. package/dist/core/utils/images/getSmallestImageDimensions.d.ts +5 -0
  141. package/dist/core/utils/images/getSmallestImageDimensions.js +9 -0
  142. package/dist/core/utils/images/handleImageEdges.d.ts +13 -0
  143. package/dist/core/utils/images/handleImageEdges.js +39 -0
  144. package/dist/core/utils/images/isActualImage.d.ts +5 -0
  145. package/dist/core/utils/images/isActualImage.js +26 -0
  146. package/dist/core/utils/images/parseAspectRatio.d.ts +1 -0
  147. package/dist/core/utils/images/parseAspectRatio.js +22 -0
  148. package/dist/core/utils/images/roundImage.d.ts +9 -0
  149. package/dist/core/utils/images/roundImage.js +27 -0
  150. package/dist/core/utils/images/roundImages.d.ts +8 -0
  151. package/dist/core/utils/images/roundImages.js +19 -0
  152. package/dist/core/utils/images/scaleImage.d.ts +8 -0
  153. package/dist/core/utils/images/scaleImage.js +36 -0
  154. package/dist/core/utils/images/scaleImages.d.ts +8 -0
  155. package/dist/core/utils/images/scaleImages.js +38 -0
  156. package/dist/core/utils/math/median.d.ts +1 -0
  157. package/dist/core/utils/math/median.js +12 -0
  158. package/dist/core/utils/math/randint.d.ts +6 -0
  159. package/dist/core/utils/math/randint.js +11 -0
  160. package/dist/core/utils/math/trimmedMedian.d.ts +1 -0
  161. package/dist/core/utils/math/trimmedMedian.js +12 -0
  162. package/dist/core/utils/svg/createSvgTextBuffer.d.ts +9 -0
  163. package/dist/core/utils/svg/createSvgTextBuffer.js +21 -0
  164. package/dist/validators/aspectRatio.d.ts +2 -0
  165. package/dist/validators/aspectRatio.js +15 -0
  166. package/dist/validators/coercion.d.ts +2 -0
  167. package/dist/validators/coercion.js +12 -0
  168. package/dist/validators/format.d.ts +2 -0
  169. package/dist/validators/format.js +15 -0
  170. package/dist/validators/hexColor.d.ts +7 -0
  171. package/dist/validators/hexColor.js +27 -0
  172. package/dist/validators/index.d.ts +95 -0
  173. package/dist/validators/index.js +64 -0
  174. package/dist/validators/outputFile.d.ts +2 -0
  175. package/dist/validators/outputFile.js +7 -0
  176. package/dist/validators/path.d.ts +3 -0
  177. package/dist/validators/path.js +18 -0
  178. package/dist/validators/sharpImageInput.d.ts +3 -0
  179. package/dist/validators/sharpImageInput.js +6 -0
  180. package/dist/validators/template.d.ts +15 -0
  181. package/dist/validators/template.js +41 -0
  182. package/package.json +26 -9
  183. package/bin/pixeli.js +0 -26
  184. package/commands/merge/collage.js +0 -83
  185. package/commands/merge/grid.js +0 -71
  186. package/commands/merge/helpers/utils.js +0 -11
  187. package/commands/merge/helpers/validations.js +0 -269
  188. package/commands/merge/index.js +0 -12
  189. package/commands/merge/masonry.js +0 -72
  190. package/lib/helpers/loadImages.js +0 -94
  191. package/lib/helpers/progressBar.js +0 -20
  192. package/lib/helpers/templateValidator.js +0 -139
  193. package/lib/helpers/utils.js +0 -208
  194. package/lib/merges/collage-merge/index.js +0 -110
  195. package/lib/merges/collage-merge/presets/artGallery.js +0 -17
  196. package/lib/merges/collage-merge/presets/dashboardShot.js +0 -18
  197. package/lib/merges/collage-merge/presets/horizontalBookSpread.js +0 -15
  198. package/lib/merges/collage-merge/presets/instagramGrid.js +0 -18
  199. package/lib/merges/collage-merge/presets/verticalBookSpread.js +0 -15
  200. package/lib/merges/grid-merge/index.js +0 -152
  201. package/lib/merges/masonry-merge/horizontal.js +0 -157
  202. package/lib/merges/masonry-merge/index.js +0 -57
  203. package/lib/merges/masonry-merge/vertical.js +0 -152
  204. package/lib/merges/merge-utils.js +0 -176
@@ -0,0 +1,73 @@
1
+ export declare const PRESETS: {
2
+ 'instagram-grid': {
3
+ canvas: {
4
+ width: number;
5
+ height: number;
6
+ columns: number;
7
+ rows: number;
8
+ };
9
+ slots: {
10
+ col: number;
11
+ row: number;
12
+ colSpan: number;
13
+ rowSpan: number;
14
+ }[];
15
+ };
16
+ 'dashboard-shot': {
17
+ canvas: {
18
+ width: number;
19
+ height: number;
20
+ columns: number;
21
+ rows: number;
22
+ };
23
+ slots: {
24
+ col: number;
25
+ row: number;
26
+ colSpan: number;
27
+ rowSpan: number;
28
+ }[];
29
+ };
30
+ 'horizontal-book-spread': {
31
+ canvas: {
32
+ width: number;
33
+ height: number;
34
+ columns: number;
35
+ rows: number;
36
+ };
37
+ slots: {
38
+ col: number;
39
+ row: number;
40
+ colSpan: number;
41
+ rowSpan: number;
42
+ }[];
43
+ };
44
+ 'vertical-book-spread': {
45
+ canvas: {
46
+ width: number;
47
+ height: number;
48
+ columns: number;
49
+ rows: number;
50
+ };
51
+ slots: {
52
+ col: number;
53
+ row: number;
54
+ colSpan: number;
55
+ rowSpan: number;
56
+ }[];
57
+ };
58
+ 'art-gallery': {
59
+ canvas: {
60
+ width: number;
61
+ height: number;
62
+ columns: number;
63
+ rows: number;
64
+ };
65
+ slots: {
66
+ col: number;
67
+ row: number;
68
+ colSpan: number;
69
+ rowSpan: number;
70
+ }[];
71
+ };
72
+ };
73
+ export declare const isValidPreset: (presetId: string) => boolean;
@@ -3,15 +3,13 @@ import dashboardShot from './presets/dashboardShot.js';
3
3
  import horizontalBookSpread from './presets/horizontalBookSpread.js';
4
4
  import verticalBookSpread from './presets/verticalBookSpread.js';
5
5
  import artGallery from './presets/artGallery.js';
6
-
7
6
  export const PRESETS = {
8
- 'instagram-grid': instagramGrid,
9
- 'dashboard-shot': dashboardShot,
10
- 'horizontal-book-spread': horizontalBookSpread,
11
- 'vertical-book-spread': verticalBookSpread,
12
- 'art-gallery': artGallery,
7
+ 'instagram-grid': instagramGrid,
8
+ 'dashboard-shot': dashboardShot,
9
+ 'horizontal-book-spread': horizontalBookSpread,
10
+ 'vertical-book-spread': verticalBookSpread,
11
+ 'art-gallery': artGallery,
13
12
  };
14
-
15
13
  export const isValidPreset = (presetId) => {
16
- return presetId in PRESETS;
14
+ return presetId in PRESETS;
17
15
  };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { configureCommandErrors } from './utils/configureCommandErrors.js';
4
+ import gridCommand from './commands/grid/index.js';
5
+ import masonryCommand from './commands/masonry/index.js';
6
+ import templateCommand from './commands/template/index.js';
7
+ import collageCommand from './commands/collage/index.js';
8
+ import pkg from '../../package.json' with { type: 'json' };
9
+ const program = new Command();
10
+ program
11
+ .name('pixeli')
12
+ .description('A lightweight command-line tool for merging multiple images into customizable grid layouts.')
13
+ .version(pkg.version);
14
+ program.addCommand(gridCommand);
15
+ program.addCommand(masonryCommand);
16
+ program.addCommand(templateCommand);
17
+ program.addCommand(collageCommand);
18
+ configureCommandErrors(program);
19
+ try {
20
+ program.parse();
21
+ }
22
+ catch (e) {
23
+ console.log(e);
24
+ }
@@ -0,0 +1,15 @@
1
+ export interface LoadImagesOptions {
2
+ input: {
3
+ files: string[] | undefined;
4
+ dir: string | undefined;
5
+ };
6
+ recursive: boolean;
7
+ count?: number;
8
+ }
9
+ export declare const loadImages: ({ input, recursive, count }: LoadImagesOptions) => Promise<{
10
+ images: Buffer<ArrayBufferLike>[];
11
+ imagePaths: string[];
12
+ ignoredPaths: string[];
13
+ }>;
14
+ export declare const loadFromFiles: (files: string[], count: number | undefined) => Promise<NonSharedBuffer[]>;
15
+ export declare const getFilepathsFromDirectory: (dir: string, recursive: boolean, depth?: number) => Promise<string[]>;
@@ -0,0 +1,74 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { isSupportedInputImage } from '../../core/helpers.js';
4
+ const MAX_RECURSION_DEPTH = 10;
5
+ const hasDir = (input) => {
6
+ return typeof input.dir === 'string';
7
+ };
8
+ export const loadImages = async ({ input, recursive, count }) => {
9
+ let filepaths = [];
10
+ let images = [];
11
+ // Get all file paths
12
+ if (input.files && input.files.length) {
13
+ filepaths = input.files;
14
+ }
15
+ else if (hasDir(input)) {
16
+ filepaths = await getFilepathsFromDirectory(input.dir, recursive);
17
+ }
18
+ // Load valid image paths
19
+ const { ignoredPaths, imagePaths } = validateFilepaths(filepaths);
20
+ images = await loadFromFiles(imagePaths, count);
21
+ // Ensure filepaths and images match
22
+ if (images.length !== filepaths.length) {
23
+ filepaths = filepaths.slice(0, images.length);
24
+ }
25
+ return { images, imagePaths, ignoredPaths };
26
+ };
27
+ export const loadFromFiles = async (files, count) => {
28
+ const loadedFiles = [];
29
+ const total = count || files.length;
30
+ for (let i = 0; i < total; i++) {
31
+ // End the loop if count is higher than number of available files
32
+ if (i >= files.length)
33
+ break;
34
+ // Load images
35
+ const filepath = files[i];
36
+ const file = await fs.readFile(filepath);
37
+ loadedFiles.push(file);
38
+ }
39
+ return loadedFiles;
40
+ };
41
+ export const getFilepathsFromDirectory = async (dir, recursive, depth = 0) => {
42
+ // Ensure recursiveness ends at the max recursion depth
43
+ if (depth >= MAX_RECURSION_DEPTH)
44
+ return [];
45
+ // Get entries
46
+ const entries = await fs.readdir(dir, { withFileTypes: true });
47
+ const files = [];
48
+ for (const entry of entries) {
49
+ const file = path.join(entry.parentPath, entry.name);
50
+ // If the entry is a file, add it to the list
51
+ if (entry.isFile()) {
52
+ files.push(file);
53
+ }
54
+ // If it's a directory AND the recursive option is true,
55
+ // recursively get all the files
56
+ else if (recursive && entry.isDirectory() && !entry.isSymbolicLink()) {
57
+ const dirPath = path.join(entry.parentPath, entry.name);
58
+ const paths = await getFilepathsFromDirectory(dirPath, recursive, depth + 1);
59
+ files.push(...paths);
60
+ }
61
+ }
62
+ return files;
63
+ };
64
+ const validateFilepaths = (filepaths) => {
65
+ const ignoredPaths = [];
66
+ const imagePaths = [];
67
+ for (const filepath of filepaths) {
68
+ if (path.basename(filepath) === '.DS_Store')
69
+ continue;
70
+ const extname = path.extname(filepath).replace('.', '');
71
+ isSupportedInputImage(extname) ? imagePaths.push(filepath) : ignoredPaths.push(filepath);
72
+ }
73
+ return { ignoredPaths, imagePaths };
74
+ };
@@ -0,0 +1,10 @@
1
+ import { SingleBar } from 'cli-progress';
2
+ import type { ProgressInfo } from '../../core/merges/types.js';
3
+ export declare class MergeProgressBar {
4
+ #private;
5
+ progressBar: SingleBar;
6
+ constructor();
7
+ startBar(phase: string): void;
8
+ updateBar(progressInfo: ProgressInfo): void;
9
+ endBar(): void;
10
+ }
@@ -0,0 +1,34 @@
1
+ import { SingleBar } from 'cli-progress';
2
+ import chalk from 'chalk';
3
+ const title = chalk.gray('Creating Image:');
4
+ const bar = chalk.blue('{bar}');
5
+ const percentage = chalk.yellow('{percentage}%');
6
+ const eta = chalk.blue('ETA: ') + chalk.yellow('{eta_formatted}');
7
+ const phase = chalk.gray('{phase}...');
8
+ const divider = chalk.blue('|');
9
+ export class MergeProgressBar {
10
+ #PROCESSING_WEIGHT = 0.95;
11
+ progressBar;
12
+ constructor() {
13
+ // Initialize progress bar
14
+ this.progressBar = new SingleBar({
15
+ format: `${title} ${divider}${bar}${divider} ${percentage} ${divider} ${eta} ${divider} ${phase} `,
16
+ barCompleteChar: '\u2588',
17
+ barIncompleteChar: '\u2591',
18
+ stopOnComplete: true,
19
+ barsize: 40,
20
+ etaBuffer: 50,
21
+ });
22
+ }
23
+ startBar(phase) {
24
+ this.progressBar.start(100, 0, { phase });
25
+ }
26
+ updateBar(progressInfo) {
27
+ const processing = progressInfo.completed / progressInfo.total;
28
+ const progress = processing * this.#PROCESSING_WEIGHT;
29
+ this.progressBar.update(progress * 100, { phase: processing === 1 ? 'Writing to file' : progressInfo.phase });
30
+ }
31
+ endBar() {
32
+ this.progressBar.update(100);
33
+ }
34
+ }
@@ -0,0 +1,29 @@
1
+ import z from 'zod';
2
+ export declare const cliCollageSchema: z.ZodObject<{
3
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
4
+ dir: z.ZodOptional<z.ZodString>;
5
+ recursive: z.ZodDefault<z.ZodBoolean>;
6
+ shuffle: z.ZodDefault<z.ZodBoolean>;
7
+ cornerRadius: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
8
+ gap: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
9
+ canvasColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
10
+ r: z.ZodNumber;
11
+ g: z.ZodNumber;
12
+ b: z.ZodNumber;
13
+ alpha: z.ZodNumber;
14
+ }, z.z.core.$strip>]>>;
15
+ borderWidth: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
16
+ borderColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
17
+ r: z.ZodNumber;
18
+ g: z.ZodNumber;
19
+ b: z.ZodNumber;
20
+ alpha: z.ZodNumber;
21
+ }, z.z.core.$strip>]>>;
22
+ output: z.ZodDefault<z.ZodString>;
23
+ aspectRatio: z.ZodPrefault<z.ZodPipe<z.z.ZodCoercedString<unknown>, z.ZodTransform<number, string>>>;
24
+ imageWidth: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
25
+ columns: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
26
+ overlapPercentage: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
27
+ rotationRange: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
28
+ imageWidthVariance: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
29
+ }, z.z.core.$strict>;
@@ -0,0 +1,38 @@
1
+ import z from 'zod';
2
+ import { VALIDATORS } from '../../validators/index.js';
3
+ export const cliCollageSchema = z
4
+ .strictObject({
5
+ files: VALIDATORS.files.optional(),
6
+ dir: VALIDATORS.dir.optional(),
7
+ recursive: VALIDATORS.recursive.default(false),
8
+ shuffle: VALIDATORS.shuffle.default(false),
9
+ cornerRadius: VALIDATORS.cliCornerRadius.default(0),
10
+ gap: VALIDATORS.cliGap.default(50),
11
+ canvasColor: VALIDATORS.canvasColor.prefault('#fff'),
12
+ borderWidth: VALIDATORS.cliBorderWidth.default(0),
13
+ borderColor: VALIDATORS.borderColor.prefault('#000'),
14
+ output: VALIDATORS.output.default('./pixeli.png'),
15
+ aspectRatio: VALIDATORS.aspectRatio.prefault('1:1'),
16
+ imageWidth: VALIDATORS.cliImageWidth.optional(),
17
+ columns: VALIDATORS.cliColumns.default(4),
18
+ overlapPercentage: VALIDATORS.cliOverlapPercentage.default(25),
19
+ rotationRange: VALIDATORS.cliRotationRange.default(7),
20
+ imageWidthVariance: VALIDATORS.cliImageWidthVariance.default(10),
21
+ })
22
+ .superRefine((opts, ctx) => {
23
+ // files XOR dir
24
+ if (opts.files && !opts.files.length && !opts.dir) {
25
+ ctx.addIssue({
26
+ code: 'custom',
27
+ message: 'You must provide either --files or --dir',
28
+ path: [],
29
+ });
30
+ }
31
+ if (opts.files && opts.files.length && opts.dir) {
32
+ ctx.addIssue({
33
+ code: 'custom',
34
+ message: 'You cannot use --files and --dir together',
35
+ path: [],
36
+ });
37
+ }
38
+ });
@@ -0,0 +1,34 @@
1
+ import z from 'zod';
2
+ export declare const cliGridSchema: z.ZodObject<{
3
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
4
+ dir: z.ZodOptional<z.ZodString>;
5
+ recursive: z.ZodDefault<z.ZodBoolean>;
6
+ shuffle: z.ZodDefault<z.ZodBoolean>;
7
+ cornerRadius: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
8
+ gap: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
9
+ canvasColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
10
+ r: z.ZodNumber;
11
+ g: z.ZodNumber;
12
+ b: z.ZodNumber;
13
+ alpha: z.ZodNumber;
14
+ }, z.z.core.$strip>]>>;
15
+ output: z.ZodDefault<z.ZodString>;
16
+ aspectRatio: z.ZodPrefault<z.ZodPipe<z.z.ZodCoercedString<unknown>, z.ZodTransform<number, string>>>;
17
+ imageWidth: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
18
+ columns: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
19
+ caption: z.ZodDefault<z.ZodBoolean>;
20
+ captionColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
21
+ r: z.ZodNumber;
22
+ g: z.ZodNumber;
23
+ b: z.ZodNumber;
24
+ alpha: z.ZodNumber;
25
+ }, z.z.core.$strip>]>>;
26
+ borderWidth: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
27
+ borderColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
28
+ r: z.ZodNumber;
29
+ g: z.ZodNumber;
30
+ b: z.ZodNumber;
31
+ alpha: z.ZodNumber;
32
+ }, z.z.core.$strip>]>>;
33
+ maxCaptionSize: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
34
+ }, z.z.core.$strict>;
@@ -0,0 +1,38 @@
1
+ import z from 'zod';
2
+ import { VALIDATORS } from '../../validators/index.js';
3
+ export const cliGridSchema = z
4
+ .strictObject({
5
+ files: VALIDATORS.files.optional(),
6
+ dir: VALIDATORS.dir.optional(),
7
+ recursive: VALIDATORS.recursive.default(false),
8
+ shuffle: VALIDATORS.shuffle.default(false),
9
+ cornerRadius: VALIDATORS.cliCornerRadius.default(0),
10
+ gap: VALIDATORS.cliGap.default(50),
11
+ canvasColor: VALIDATORS.canvasColor.prefault('#fff'),
12
+ output: VALIDATORS.output.default('./pixeli.png'),
13
+ aspectRatio: VALIDATORS.aspectRatio.prefault('1:1'),
14
+ imageWidth: VALIDATORS.cliImageWidth.optional(),
15
+ columns: VALIDATORS.cliColumns.default(4),
16
+ caption: VALIDATORS.caption.default(false),
17
+ captionColor: VALIDATORS.captionColor.prefault('#000'),
18
+ borderWidth: VALIDATORS.cliBorderWidth.default(0),
19
+ borderColor: VALIDATORS.borderColor.prefault("#000"),
20
+ maxCaptionSize: VALIDATORS.cliMaxCaptionSize.default(100),
21
+ })
22
+ .superRefine((opts, ctx) => {
23
+ // files XOR dir
24
+ if (opts.files && !opts.files.length && !opts.dir) {
25
+ ctx.addIssue({
26
+ code: 'custom',
27
+ message: 'You must provide either --files or --dir',
28
+ path: [],
29
+ });
30
+ }
31
+ if (opts.files && opts.files.length && opts.dir) {
32
+ ctx.addIssue({
33
+ code: 'custom',
34
+ message: 'You cannot use --files and --dir together',
35
+ path: [],
36
+ });
37
+ }
38
+ });
@@ -0,0 +1,62 @@
1
+ import z from 'zod';
2
+ export declare const cliMasonrySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ flow: z.ZodLiteral<"vertical">;
4
+ columnWidth: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
5
+ canvasHeight: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>;
6
+ vAlign: z.ZodDefault<z.ZodEnum<{
7
+ justified: "justified";
8
+ top: "top";
9
+ middle: "middle";
10
+ bottom: "bottom";
11
+ }>>;
12
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
13
+ dir: z.ZodOptional<z.ZodString>;
14
+ recursive: z.ZodDefault<z.ZodBoolean>;
15
+ shuffle: z.ZodDefault<z.ZodBoolean>;
16
+ cornerRadius: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
17
+ gap: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
18
+ canvasColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
19
+ r: z.ZodNumber;
20
+ g: z.ZodNumber;
21
+ b: z.ZodNumber;
22
+ alpha: z.ZodNumber;
23
+ }, z.z.core.$strip>]>>;
24
+ borderWidth: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
25
+ borderColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
26
+ r: z.ZodNumber;
27
+ g: z.ZodNumber;
28
+ b: z.ZodNumber;
29
+ alpha: z.ZodNumber;
30
+ }, z.z.core.$strip>]>>;
31
+ output: z.ZodDefault<z.ZodString>;
32
+ }, z.z.core.$strip>, z.ZodObject<{
33
+ flow: z.ZodDefault<z.ZodLiteral<"horizontal">>;
34
+ rowHeight: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
35
+ canvasWidth: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>;
36
+ hAlign: z.ZodDefault<z.ZodEnum<{
37
+ left: "left";
38
+ center: "center";
39
+ right: "right";
40
+ justified: "justified";
41
+ }>>;
42
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
43
+ dir: z.ZodOptional<z.ZodString>;
44
+ recursive: z.ZodDefault<z.ZodBoolean>;
45
+ shuffle: z.ZodDefault<z.ZodBoolean>;
46
+ cornerRadius: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
47
+ gap: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
48
+ canvasColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
49
+ r: z.ZodNumber;
50
+ g: z.ZodNumber;
51
+ b: z.ZodNumber;
52
+ alpha: z.ZodNumber;
53
+ }, z.z.core.$strip>]>>;
54
+ borderWidth: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
55
+ borderColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
56
+ r: z.ZodNumber;
57
+ g: z.ZodNumber;
58
+ b: z.ZodNumber;
59
+ alpha: z.ZodNumber;
60
+ }, z.z.core.$strip>]>>;
61
+ output: z.ZodDefault<z.ZodString>;
62
+ }, z.z.core.$strip>], "flow">;
@@ -0,0 +1,62 @@
1
+ import z from 'zod';
2
+ import { VALIDATORS } from '../../validators/index.js';
3
+ const baseCliMasonryOptions = z.object({
4
+ files: VALIDATORS.files.optional(),
5
+ dir: VALIDATORS.dir.optional(),
6
+ recursive: VALIDATORS.recursive.default(false),
7
+ shuffle: VALIDATORS.shuffle.default(false),
8
+ cornerRadius: VALIDATORS.cliCornerRadius.default(0),
9
+ gap: VALIDATORS.cliGap.default(50),
10
+ canvasColor: VALIDATORS.canvasColor.prefault('#fff'),
11
+ borderWidth: VALIDATORS.cliBorderWidth.default(0),
12
+ borderColor: VALIDATORS.borderColor.prefault('#000'),
13
+ output: VALIDATORS.output.default('./pixeli.png'),
14
+ flow: VALIDATORS.flow.default('horizontal'),
15
+ });
16
+ const horizontalCliMasonryOptions = z.object({
17
+ ...baseCliMasonryOptions.shape,
18
+ flow: z.literal('horizontal').default('horizontal'), // default() ensures proper command line defaults
19
+ rowHeight: VALIDATORS.cliRowHeight.optional(),
20
+ canvasWidth: VALIDATORS.cliCanvasWidth,
21
+ hAlign: VALIDATORS.hAlign.default('justified'),
22
+ });
23
+ const verticalCliMasonryOptions = z.object({
24
+ ...baseCliMasonryOptions.shape,
25
+ flow: z.literal('vertical'),
26
+ columnWidth: VALIDATORS.cliColumnWidth.optional(),
27
+ canvasHeight: VALIDATORS.cliCanvasHeight,
28
+ vAlign: VALIDATORS.vAlign.default('justified'),
29
+ });
30
+ export const cliMasonrySchema = z
31
+ .discriminatedUnion('flow', [verticalCliMasonryOptions, horizontalCliMasonryOptions])
32
+ .superRefine((opts, ctx) => {
33
+ // files XOR dir
34
+ if (opts.files && !opts.files.length && !opts.dir) {
35
+ ctx.addIssue({
36
+ code: 'custom',
37
+ message: 'You must provide either --files or --dir',
38
+ path: [],
39
+ });
40
+ }
41
+ if (opts.files && opts.files.length && opts.dir) {
42
+ ctx.addIssue({
43
+ code: 'custom',
44
+ message: 'You cannot use --files and --dir together',
45
+ path: [],
46
+ });
47
+ }
48
+ if (opts.flow === 'horizontal' && opts.canvasWidth <= opts.gap * 2) {
49
+ ctx.addIssue({
50
+ code: 'custom',
51
+ message: "Canvas is too small to place images in. Increase 'canvasWidth'.",
52
+ path: ['canvasWidth'],
53
+ });
54
+ }
55
+ if (opts.flow === 'vertical' && opts.canvasHeight <= opts.gap * 2) {
56
+ ctx.addIssue({
57
+ code: 'custom',
58
+ message: "Canvas is too small to place images in. Increase 'canvasHeight'.",
59
+ path: ['canvasHeight'],
60
+ });
61
+ }
62
+ });
@@ -0,0 +1,31 @@
1
+ import z from 'zod';
2
+ export declare const cliTemplateSchema: z.ZodObject<{
3
+ files: z.ZodOptional<z.ZodArray<z.ZodString>>;
4
+ dir: z.ZodOptional<z.ZodString>;
5
+ recursive: z.ZodDefault<z.ZodBoolean>;
6
+ shuffle: z.ZodDefault<z.ZodBoolean>;
7
+ cornerRadius: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
8
+ gap: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
9
+ canvasColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
10
+ r: z.ZodNumber;
11
+ g: z.ZodNumber;
12
+ b: z.ZodNumber;
13
+ alpha: z.ZodNumber;
14
+ }, z.z.core.$strip>]>>;
15
+ borderWidth: z.ZodDefault<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>>;
16
+ borderColor: z.ZodPrefault<z.ZodUnion<readonly [z.ZodPipe<z.ZodString, z.ZodTransform<import("../../core/utils/colors/types.js").RGBA, string>>, z.ZodObject<{
17
+ r: z.ZodNumber;
18
+ g: z.ZodNumber;
19
+ b: z.ZodNumber;
20
+ alpha: z.ZodNumber;
21
+ }, z.z.core.$strip>]>>;
22
+ output: z.ZodDefault<z.ZodString>;
23
+ template: z.ZodOptional<z.ZodString>;
24
+ preset: z.ZodOptional<z.ZodEnum<{
25
+ "instagram-grid": "instagram-grid";
26
+ "dashboard-shot": "dashboard-shot";
27
+ "horizontal-book-spread": "horizontal-book-spread";
28
+ "vertical-book-spread": "vertical-book-spread";
29
+ "art-gallery": "art-gallery";
30
+ }>>;
31
+ }, z.z.core.$strict>;
@@ -0,0 +1,49 @@
1
+ import z from 'zod';
2
+ import { VALIDATORS } from '../../validators/index.js';
3
+ export const cliTemplateSchema = z
4
+ .strictObject({
5
+ files: VALIDATORS.files.optional(),
6
+ dir: VALIDATORS.dir.optional(),
7
+ recursive: VALIDATORS.recursive.default(false),
8
+ shuffle: VALIDATORS.shuffle.default(false),
9
+ cornerRadius: VALIDATORS.cliCornerRadius.default(0),
10
+ gap: VALIDATORS.cliGap.default(50),
11
+ canvasColor: VALIDATORS.canvasColor.prefault('#fff'),
12
+ borderWidth: VALIDATORS.cliBorderWidth.default(0),
13
+ borderColor: VALIDATORS.borderColor.prefault('#000'),
14
+ output: VALIDATORS.output.default('./pixeli.png'),
15
+ template: VALIDATORS.cliTemplate.optional(),
16
+ preset: VALIDATORS.preset.optional(),
17
+ })
18
+ .superRefine((opts, ctx) => {
19
+ // files XOR dir
20
+ if (opts.files && !opts.files.length && !opts.dir) {
21
+ ctx.addIssue({
22
+ code: 'custom',
23
+ message: 'You must provide either --files or --dir',
24
+ path: [],
25
+ });
26
+ }
27
+ if (opts.files && opts.files.length && opts.dir) {
28
+ ctx.addIssue({
29
+ code: 'custom',
30
+ message: 'You cannot use --files and --dir together',
31
+ path: [],
32
+ });
33
+ }
34
+ // template XOR preset
35
+ if (!opts.template && !opts.preset) {
36
+ ctx.addIssue({
37
+ code: 'custom',
38
+ message: 'You must provide either --template or --preset',
39
+ path: [],
40
+ });
41
+ }
42
+ if (opts.template && opts.preset) {
43
+ ctx.addIssue({
44
+ code: 'custom',
45
+ message: 'You cannot use --template and --preset together',
46
+ path: [],
47
+ });
48
+ }
49
+ });
@@ -0,0 +1,8 @@
1
+ import z from 'zod';
2
+ import { Command } from 'commander';
3
+ interface CommandBuilderOption {
4
+ flags: string;
5
+ description: string;
6
+ }
7
+ export declare const buildCommandFromSchema: <Shape extends z.ZodRawShape>(name: string, description: string, schema: z.ZodObject<Shape> | z.ZodUnion, args: Record<string, CommandBuilderOption>, options: Record<string, CommandBuilderOption>) => Command;
8
+ export {};