emoji-banner-generator 1.0.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -0
  3. package/dist/animation.d.ts +14 -0
  4. package/dist/animation.d.ts.map +1 -0
  5. package/dist/animation.js +194 -0
  6. package/dist/animation.js.map +1 -0
  7. package/dist/bitmap.d.ts +25 -0
  8. package/dist/bitmap.d.ts.map +1 -0
  9. package/dist/bitmap.js +141 -0
  10. package/dist/bitmap.js.map +1 -0
  11. package/dist/cli.d.ts +19 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +174 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/clipboard.d.ts +17 -0
  16. package/dist/clipboard.d.ts.map +1 -0
  17. package/dist/clipboard.js +47 -0
  18. package/dist/clipboard.js.map +1 -0
  19. package/dist/emoji.d.ts +25 -0
  20. package/dist/emoji.d.ts.map +1 -0
  21. package/dist/emoji.js +180 -0
  22. package/dist/emoji.js.map +1 -0
  23. package/dist/fonts.d.ts +26 -0
  24. package/dist/fonts.d.ts.map +1 -0
  25. package/dist/fonts.js +551 -0
  26. package/dist/fonts.js.map +1 -0
  27. package/dist/index.d.ts +7 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +108 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/output.d.ts +26 -0
  32. package/dist/output.d.ts.map +1 -0
  33. package/dist/output.js +113 -0
  34. package/dist/output.js.map +1 -0
  35. package/dist/renderer.d.ts +18 -0
  36. package/dist/renderer.d.ts.map +1 -0
  37. package/dist/renderer.js +247 -0
  38. package/dist/renderer.js.map +1 -0
  39. package/dist/slack.d.ts +35 -0
  40. package/dist/slack.d.ts.map +1 -0
  41. package/dist/slack.js +129 -0
  42. package/dist/slack.js.map +1 -0
  43. package/dist/themes.d.ts +31 -0
  44. package/dist/themes.d.ts.map +1 -0
  45. package/dist/themes.js +84 -0
  46. package/dist/themes.js.map +1 -0
  47. package/dist/types.d.ts +113 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +5 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +57 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Output module
3
+ * Handles file output
4
+ */
5
+ import type { BannerResult } from './types.js';
6
+ /**
7
+ * Save banner result to text file
8
+ */
9
+ export declare function saveToFile(result: BannerResult, outputDir: string, filename?: string): Promise<string>;
10
+ /**
11
+ * Save raw banner text
12
+ */
13
+ export declare function saveRawText(text: string, outputPath: string): Promise<string>;
14
+ /**
15
+ * Check if a path is writable
16
+ */
17
+ export declare function isWritable(dirPath: string): Promise<boolean>;
18
+ /**
19
+ * Ensure directory exists
20
+ */
21
+ export declare function ensureDir(dirPath: string): Promise<void>;
22
+ /**
23
+ * Generate unique filename if file exists
24
+ */
25
+ export declare function getUniqueFilename(dirPath: string, baseName: string, extension: string): Promise<string>;
26
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkC/C;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,MAAqB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CASjB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASlE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9D;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
package/dist/output.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Output module
3
+ * Handles file output
4
+ */
5
+ import fs from 'fs/promises';
6
+ import path from 'path';
7
+ /**
8
+ * Sanitize filename to prevent path traversal attacks
9
+ */
10
+ function sanitizeFilename(filename) {
11
+ // Remove path traversal characters and other dangerous patterns
12
+ return filename
13
+ .replace(/\.\./g, '')
14
+ .replace(/[<>:"|?*]/g, '')
15
+ .replace(/^\.+/, '')
16
+ .trim();
17
+ }
18
+ /**
19
+ * Validate and resolve output path safely
20
+ */
21
+ async function validateOutputPath(outputPath) {
22
+ // Resolve to absolute path
23
+ const absolutePath = path.resolve(outputPath);
24
+ // Check if directory exists, create if not
25
+ const dir = path.dirname(absolutePath);
26
+ try {
27
+ await fs.access(dir);
28
+ }
29
+ catch {
30
+ // Create directory recursively
31
+ await fs.mkdir(dir, { recursive: true });
32
+ }
33
+ return absolutePath;
34
+ }
35
+ /**
36
+ * Save banner result to text file
37
+ */
38
+ export async function saveToFile(result, outputDir, filename = 'banner.txt') {
39
+ const sanitizedFilename = sanitizeFilename(filename);
40
+ if (!sanitizedFilename) {
41
+ throw new Error('Invalid filename');
42
+ }
43
+ const fullPath = path.join(outputDir, sanitizedFilename);
44
+ const validatedPath = await validateOutputPath(fullPath);
45
+ // Ensure we're not writing outside the intended directory
46
+ const resolvedDir = path.resolve(outputDir);
47
+ if (!validatedPath.startsWith(resolvedDir)) {
48
+ throw new Error('Invalid output path: path traversal detected');
49
+ }
50
+ await fs.writeFile(validatedPath, result.text, 'utf-8');
51
+ return validatedPath;
52
+ }
53
+ /**
54
+ * Save raw banner text
55
+ */
56
+ export async function saveRawText(text, outputPath) {
57
+ const sanitizedFilename = sanitizeFilename(path.basename(outputPath));
58
+ const dir = path.dirname(outputPath);
59
+ const fullPath = path.join(dir, sanitizedFilename);
60
+ const validatedPath = await validateOutputPath(fullPath);
61
+ await fs.writeFile(validatedPath, text, 'utf-8');
62
+ return validatedPath;
63
+ }
64
+ /**
65
+ * Check if a path is writable
66
+ */
67
+ export async function isWritable(dirPath) {
68
+ try {
69
+ const testFile = path.join(dirPath, `.write-test-${Date.now()}`);
70
+ await fs.writeFile(testFile, '');
71
+ await fs.unlink(testFile);
72
+ return true;
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ /**
79
+ * Ensure directory exists
80
+ */
81
+ export async function ensureDir(dirPath) {
82
+ try {
83
+ await fs.access(dirPath);
84
+ }
85
+ catch {
86
+ await fs.mkdir(dirPath, { recursive: true });
87
+ }
88
+ }
89
+ /**
90
+ * Generate unique filename if file exists
91
+ */
92
+ export async function getUniqueFilename(dirPath, baseName, extension) {
93
+ const sanitizedBase = sanitizeFilename(baseName);
94
+ let filename = `${sanitizedBase}.${extension}`;
95
+ let counter = 1;
96
+ while (true) {
97
+ try {
98
+ await fs.access(path.join(dirPath, filename));
99
+ // File exists, try next number
100
+ filename = `${sanitizedBase}-${counter}.${extension}`;
101
+ counter++;
102
+ // Safety limit
103
+ if (counter > 1000) {
104
+ throw new Error('Too many files with same name');
105
+ }
106
+ }
107
+ catch {
108
+ // File doesn't exist, we can use this name
109
+ return filename;
110
+ }
111
+ }
112
+ }
113
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Renderer module
3
+ * Converts bitmap to emoji text with various modes
4
+ */
5
+ import type { Bitmap, EmojiMode, RenderConfig, BannerResult } from './types.js';
6
+ /**
7
+ * Render bitmap to emoji text
8
+ */
9
+ export declare function renderBitmap(bitmap: Bitmap, config: RenderConfig): BannerResult;
10
+ /**
11
+ * Render bitmap with custom selector function
12
+ */
13
+ export declare function renderBitmapCustom(bitmap: Bitmap, selector: (row: number, col: number, isForeground: boolean) => string): string;
14
+ /**
15
+ * Create default render config
16
+ */
17
+ export declare function createDefaultConfig(foregroundEmojis: string[], backgroundEmoji?: string, mode?: EmojiMode, theme?: string, borderEmoji?: string): RenderConfig;
18
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAgKhF;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,GACnB,YAAY,CA0Ed;AA6BD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,KAAK,MAAM,GACpE,MAAM,CAYR;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,eAAe,CAAC,EAAE,MAAM,EACxB,IAAI,GAAE,SAAoB,EAC1B,KAAK,GAAE,MAAkB,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,YAAY,CAQd"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Renderer module
3
+ * Converts bitmap to emoji text with various modes
4
+ */
5
+ import { getBackgroundEmoji } from './emoji.js';
6
+ import { getThemeEmojis } from './themes.js';
7
+ // Minimal emoji / wide-char detection for width calculation
8
+ const EMOJI_REGEX = /[\u{1F300}-\u{1FAFF}\u{1F600}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE0F}]/u;
9
+ const EXTENDED_PICTO_REGEX = /\p{Extended_Pictographic}/u;
10
+ const WIDE_CHAR_REGEX = /[\u3000\u3001-\u303F\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF]/u;
11
+ function isLikelyCustomEmoji(value) {
12
+ const trimmed = value.trim();
13
+ if (!trimmed)
14
+ return false;
15
+ if (EXTENDED_PICTO_REGEX.test(trimmed) || EMOJI_REGEX.test(trimmed) || WIDE_CHAR_REGEX.test(trimmed)) {
16
+ return false;
17
+ }
18
+ // Treat colon-wrapped or simple alias-like tokens as custom emoji (Slack-style)
19
+ return /^:?[a-zA-Z0-9_-]{1,64}:?$/.test(trimmed) && !/\s/.test(trimmed);
20
+ }
21
+ const graphemeSegmenter = (() => {
22
+ try {
23
+ if (typeof Intl !== 'undefined' &&
24
+ typeof Intl
25
+ .Segmenter === 'function') {
26
+ return new Intl.Segmenter('en', { granularity: 'grapheme' });
27
+ }
28
+ }
29
+ catch {
30
+ // ignore
31
+ }
32
+ return null;
33
+ })();
34
+ function getGraphemes(str) {
35
+ if (graphemeSegmenter) {
36
+ return Array.from(graphemeSegmenter.segment(str), (segment) => segment.segment);
37
+ }
38
+ return [...str];
39
+ }
40
+ /**
41
+ * Seeded random number generator for reproducible results
42
+ */
43
+ class SeededRandom {
44
+ seed;
45
+ constructor(seed = Date.now()) {
46
+ this.seed = seed;
47
+ }
48
+ next() {
49
+ this.seed = (this.seed * 1103515245 + 12345) & 0x7fffffff;
50
+ return this.seed / 0x7fffffff;
51
+ }
52
+ nextInt(max) {
53
+ return Math.floor(this.next() * max);
54
+ }
55
+ }
56
+ /**
57
+ * Approximate display width (emoji treated as double-width).
58
+ */
59
+ function getDisplayWidth(str) {
60
+ if (isLikelyCustomEmoji(str)) {
61
+ return 2;
62
+ }
63
+ let width = 0;
64
+ for (const char of getGraphemes(str)) {
65
+ if (char === '\u3000') {
66
+ width += 2;
67
+ }
68
+ else if (EXTENDED_PICTO_REGEX.test(char) || EMOJI_REGEX.test(char) || WIDE_CHAR_REGEX.test(char)) {
69
+ width += 2;
70
+ }
71
+ else {
72
+ width += 1;
73
+ }
74
+ }
75
+ return width;
76
+ }
77
+ /**
78
+ * Pad a string with spaces until it reaches the target display width.
79
+ */
80
+ function padToWidth(str, targetWidth) {
81
+ let result = str;
82
+ let width = getDisplayWidth(str);
83
+ while (width < targetWidth) {
84
+ result += ' ';
85
+ width += 1;
86
+ }
87
+ return result;
88
+ }
89
+ /**
90
+ * Fit text to the target width, padding or replacing when too wide to keep the grid stable.
91
+ */
92
+ function fitToWidth(str, targetWidth) {
93
+ const current = getDisplayWidth(str);
94
+ if (current === targetWidth)
95
+ return str;
96
+ if (current < targetWidth) {
97
+ return padToWidth(str, targetWidth);
98
+ }
99
+ // If wider, fall back to spaces to avoid breaking alignment.
100
+ return padToWidth('', targetWidth);
101
+ }
102
+ /**
103
+ * Select emoji based on mode, position, and available emojis
104
+ */
105
+ function selectEmoji(emojis, row, col, totalRows, totalCols, mode, random) {
106
+ if (emojis.length === 1) {
107
+ return emojis[0];
108
+ }
109
+ switch (mode) {
110
+ case 'random':
111
+ return emojis[random.nextInt(emojis.length)];
112
+ case 'row':
113
+ return emojis[row % emojis.length];
114
+ case 'column':
115
+ return emojis[col % emojis.length];
116
+ case 'row-gradient': {
117
+ // Gradient across rows - smoothly transition through emojis
118
+ const rowProgress = totalRows > 1 ? row / (totalRows - 1) : 0;
119
+ const emojiIndex = Math.floor(rowProgress * (emojis.length - 1));
120
+ return emojis[Math.min(emojiIndex, emojis.length - 1)];
121
+ }
122
+ case 'column-gradient': {
123
+ // Gradient across columns - smoothly transition through emojis
124
+ const colProgress = totalCols > 1 ? col / (totalCols - 1) : 0;
125
+ const emojiIndex = Math.floor(colProgress * (emojis.length - 1));
126
+ return emojis[Math.min(emojiIndex, emojis.length - 1)];
127
+ }
128
+ default:
129
+ return emojis[0];
130
+ }
131
+ }
132
+ /**
133
+ * Render bitmap to emoji text
134
+ */
135
+ export function renderBitmap(bitmap, config) {
136
+ const { foregroundEmojis, backgroundEmoji, borderEmoji, mode, theme } = config;
137
+ // Get theme emojis if applicable
138
+ const emojis = theme === 'github'
139
+ ? getThemeEmojis('github')
140
+ : foregroundEmojis;
141
+ // Use background emoji or default
142
+ const bgEmoji = backgroundEmoji || getBackgroundEmoji();
143
+ const border = borderEmoji ?? null;
144
+ // Normalize cell width so backgrounds and foregrounds align visually
145
+ const sampleEmojis = theme === 'github' ? emojis : foregroundEmojis;
146
+ const widthCandidates = [...sampleEmojis, bgEmoji];
147
+ if (border)
148
+ widthCandidates.push(border);
149
+ const maxWidth = Math.max(...widthCandidates.map(getDisplayWidth));
150
+ // Anchor width to foreground so non-emoji backgrounds don't widen cells unexpectedly
151
+ const cellWidth = Math.max(maxWidth, 2);
152
+ const paddedBackground = fitToWidth(bgEmoji, cellWidth);
153
+ const paddedBorder = border ? fitToWidth(border, cellWidth) : null;
154
+ const height = bitmap.length;
155
+ const width = height > 0 ? bitmap[0].length : 0;
156
+ const random = new SeededRandom(42); // Fixed seed for reproducibility
157
+ let lines = [];
158
+ for (let row = 0; row < height; row++) {
159
+ let line = '';
160
+ for (let col = 0; col < width; col++) {
161
+ const isForeground = bitmap[row][col];
162
+ if (isForeground) {
163
+ const rawEmoji = theme === 'github'
164
+ ? emojis[calculateGitHubIntensity(row, col, height, width, random)]
165
+ : selectEmoji(emojis, row, col, height, width, mode, random);
166
+ const paddedEmoji = fitToWidth(rawEmoji, cellWidth);
167
+ if (theme === 'github') {
168
+ // For GitHub theme, vary intensity based on position
169
+ line += paddedEmoji;
170
+ }
171
+ else {
172
+ line += paddedEmoji;
173
+ }
174
+ }
175
+ else {
176
+ line += paddedBackground;
177
+ }
178
+ }
179
+ lines.push(line);
180
+ }
181
+ if (paddedBorder) {
182
+ const topBottom = paddedBorder.repeat(width + 2);
183
+ lines = [
184
+ topBottom,
185
+ ...lines.map((line) => paddedBorder + line + paddedBorder),
186
+ topBottom,
187
+ ];
188
+ }
189
+ const finalWidth = paddedBorder ? width + 2 : width;
190
+ const finalHeight = paddedBorder ? height + 2 : height;
191
+ const text = lines.join('\n');
192
+ return {
193
+ text,
194
+ backgroundEmoji: bgEmoji,
195
+ borderEmoji: border ?? undefined,
196
+ bitmap,
197
+ width: finalWidth,
198
+ height: finalHeight,
199
+ };
200
+ }
201
+ /**
202
+ * Calculate GitHub contribution-style intensity (0-4)
203
+ */
204
+ function calculateGitHubIntensity(row, col, totalRows, totalCols, random) {
205
+ // Create a somewhat random but clustered pattern
206
+ // Similar to how GitHub contributions look
207
+ const baseIntensity = random.next();
208
+ // Add some spatial coherence
209
+ const spatialNoise = Math.sin(row * 0.5) * Math.cos(col * 0.5) * 0.3;
210
+ const combined = baseIntensity + spatialNoise;
211
+ // Map to 0-4 range (GitHub has 5 levels including 0)
212
+ // But we only use 1-4 for foreground (0 is background)
213
+ if (combined < 0.25)
214
+ return 1;
215
+ if (combined < 0.5)
216
+ return 2;
217
+ if (combined < 0.75)
218
+ return 3;
219
+ return 4;
220
+ }
221
+ /**
222
+ * Render bitmap with custom selector function
223
+ */
224
+ export function renderBitmapCustom(bitmap, selector) {
225
+ const lines = [];
226
+ for (let row = 0; row < bitmap.length; row++) {
227
+ let line = '';
228
+ for (let col = 0; col < bitmap[row].length; col++) {
229
+ line += selector(row, col, bitmap[row][col]);
230
+ }
231
+ lines.push(line);
232
+ }
233
+ return lines.join('\n');
234
+ }
235
+ /**
236
+ * Create default render config
237
+ */
238
+ export function createDefaultConfig(foregroundEmojis, backgroundEmoji, mode = 'random', theme = 'default', borderEmoji) {
239
+ return {
240
+ foregroundEmojis,
241
+ backgroundEmoji: backgroundEmoji || getBackgroundEmoji(),
242
+ borderEmoji,
243
+ mode,
244
+ theme: theme,
245
+ };
246
+ }
247
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Slack format module
3
+ * Generates Slack Block Kit JSON format output
4
+ */
5
+ import type { BannerResult, SlackMessage } from './types.js';
6
+ /**
7
+ * Convert banner result to Slack Block Kit format
8
+ * This format ensures emojis align properly in Slack
9
+ */
10
+ export declare function toSlackFormat(result: BannerResult): SlackMessage;
11
+ /**
12
+ * Convert to Slack-compatible plain text
13
+ * This version uses a rich_text block for better emoji handling
14
+ */
15
+ export declare function toSlackRichText(result: BannerResult): SlackMessage;
16
+ /**
17
+ * Convert to simple Slack message format (for direct posting)
18
+ */
19
+ export declare function toSlackSimple(result: BannerResult): {
20
+ text: string;
21
+ };
22
+ /**
23
+ * Generate JSON string output for Slack API
24
+ */
25
+ export declare function generateSlackJson(result: BannerResult): string;
26
+ /**
27
+ * Validate Slack message structure
28
+ */
29
+ export declare function validateSlackMessage(message: SlackMessage): boolean;
30
+ /**
31
+ * Get Slack-compatible emoji name from Unicode emoji
32
+ * Note: This is a simplified mapping, Slack uses its own emoji names
33
+ */
34
+ export declare function toSlackEmojiName(emoji: string): string;
35
+ //# sourceMappingURL=slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAQzE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAgChE;AA0BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAsBlE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAKpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAG9D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAanE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAItD"}
package/dist/slack.js ADDED
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Slack format module
3
+ * Generates Slack Block Kit JSON format output
4
+ */
5
+ /**
6
+ * Maximum characters per Slack text block
7
+ * Slack has a limit of 3000 characters per text block
8
+ */
9
+ const SLACK_TEXT_LIMIT = 3000;
10
+ /**
11
+ * Convert banner result to Slack Block Kit format
12
+ * This format ensures emojis align properly in Slack
13
+ */
14
+ export function toSlackFormat(result) {
15
+ const lines = result.text.split('\n');
16
+ const blocks = [];
17
+ // Use a section with mrkdwn for each line to preserve spacing
18
+ // Wrap each line in a code block using backticks for monospace
19
+ // This helps with alignment
20
+ // Group lines to stay within Slack's character limit
21
+ let currentText = '';
22
+ for (const line of lines) {
23
+ // Use zero-width spaces and special formatting to maintain alignment
24
+ const formattedLine = formatLineForSlack(line);
25
+ if (currentText.length + formattedLine.length + 1 > SLACK_TEXT_LIMIT) {
26
+ // Push current block and start new one
27
+ if (currentText) {
28
+ blocks.push(createTextBlock(currentText));
29
+ }
30
+ currentText = formattedLine;
31
+ }
32
+ else {
33
+ currentText += (currentText ? '\n' : '') + formattedLine;
34
+ }
35
+ }
36
+ // Push remaining text
37
+ if (currentText) {
38
+ blocks.push(createTextBlock(currentText));
39
+ }
40
+ return { blocks };
41
+ }
42
+ /**
43
+ * Format a single line for Slack display
44
+ * Uses techniques to maintain emoji alignment
45
+ */
46
+ function formatLineForSlack(line) {
47
+ // In Slack, emojis in mrkdwn should align properly
48
+ // We just need to ensure consistent spacing
49
+ return line;
50
+ }
51
+ /**
52
+ * Create a Slack text block
53
+ */
54
+ function createTextBlock(text) {
55
+ return {
56
+ type: 'section',
57
+ text: {
58
+ type: 'mrkdwn',
59
+ text: text,
60
+ emoji: true,
61
+ },
62
+ };
63
+ }
64
+ /**
65
+ * Convert to Slack-compatible plain text
66
+ * This version uses a rich_text block for better emoji handling
67
+ */
68
+ export function toSlackRichText(result) {
69
+ const lines = result.text.split('\n');
70
+ // Create rich_text block with elements
71
+ const elements = lines.map((line) => ({
72
+ type: 'rich_text_preformatted',
73
+ elements: [
74
+ {
75
+ type: 'text',
76
+ text: line,
77
+ },
78
+ ],
79
+ }));
80
+ return {
81
+ blocks: [
82
+ {
83
+ type: 'rich_text',
84
+ elements,
85
+ },
86
+ ],
87
+ };
88
+ }
89
+ /**
90
+ * Convert to simple Slack message format (for direct posting)
91
+ */
92
+ export function toSlackSimple(result) {
93
+ // Use triple backticks for code block (monospace)
94
+ return {
95
+ text: '```\n' + result.text + '\n```',
96
+ };
97
+ }
98
+ /**
99
+ * Generate JSON string output for Slack API
100
+ */
101
+ export function generateSlackJson(result) {
102
+ const message = toSlackFormat(result);
103
+ return JSON.stringify(message, null, 2);
104
+ }
105
+ /**
106
+ * Validate Slack message structure
107
+ */
108
+ export function validateSlackMessage(message) {
109
+ if (!message || !Array.isArray(message.blocks)) {
110
+ return false;
111
+ }
112
+ // Check each block has required fields
113
+ for (const block of message.blocks) {
114
+ if (!block.type) {
115
+ return false;
116
+ }
117
+ }
118
+ return true;
119
+ }
120
+ /**
121
+ * Get Slack-compatible emoji name from Unicode emoji
122
+ * Note: This is a simplified mapping, Slack uses its own emoji names
123
+ */
124
+ export function toSlackEmojiName(emoji) {
125
+ // For most emojis, Slack accepts the Unicode directly
126
+ // But for some, you might need the :name: format
127
+ return emoji;
128
+ }
129
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Theme module
3
+ * Provides themed emoji sets for different visual styles
4
+ */
5
+ import type { Theme, GitHubLevel } from './types.js';
6
+ /**
7
+ * Get emojis for a specific theme
8
+ */
9
+ export declare function getThemeEmojis(theme: Theme): string[];
10
+ /**
11
+ * Get background emoji for a theme
12
+ */
13
+ export declare function getThemeBackground(theme: Theme): string;
14
+ /**
15
+ * Check if a theme is valid
16
+ */
17
+ export declare function isValidTheme(theme: string): theme is Theme;
18
+ /**
19
+ * Get all available theme names
20
+ */
21
+ export declare function getAvailableThemes(): Theme[];
22
+ /**
23
+ * GitHub theme intensity calculator
24
+ * Returns 1-4 for foreground pixels with varying intensity
25
+ */
26
+ export declare function getGitHubIntensity(row: number, col: number, seed?: number): GitHubLevel;
27
+ /**
28
+ * Get description for a theme
29
+ */
30
+ export declare function getThemeDescription(theme: Theme): string;
31
+ //# sourceMappingURL=themes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgCrD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAErD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAKvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,KAAK,CAE1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,KAAK,EAAE,CAE5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,MAAU,GACf,WAAW,CAQb;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAMxD"}