From 51db0d9e387ecd02398f29eb4825b8cabddd20f3 Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Wed, 8 May 2024 08:57:39 -0300
Subject: [PATCH] fix(emoji): Use colorful version of warning emoji (#28888)

---
 lib/modules/platform/github/index.ts          |  1 +
 lib/util/emoji.spec.ts                        | 33 ++++++++---
 lib/util/emoji.ts                             | 55 +++++++++++++------
 .../repository/errors-warnings.spec.ts        |  8 +--
 4 files changed, 67 insertions(+), 30 deletions(-)

diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts
index 9357a3adc9..a0873b7d0c 100644
--- a/lib/modules/platform/github/index.ts
+++ b/lib/modules/platform/github/index.ts
@@ -1950,6 +1950,7 @@ export function massageMarkdown(input: string): string {
     .replace(regEx(/]: https:\/\/github\.com\//g), ']: https://togithub.com/')
     .replace('> ℹ **Note**\n> \n', '> [!NOTE]\n')
     .replace('> âš  **Warning**\n> \n', '> [!WARNING]\n')
+    .replace('> ⚠️ **Warning**\n> \n', '> [!WARNING]\n')
     .replace('> ❗ **Important**\n> \n', '> [!IMPORTANT]\n');
   return smartTruncate(massagedInput, GitHubMaxPrBodyLen);
 }
diff --git a/lib/util/emoji.spec.ts b/lib/util/emoji.spec.ts
index 97e9c9309b..9dc475a838 100644
--- a/lib/util/emoji.spec.ts
+++ b/lib/util/emoji.spec.ts
@@ -21,6 +21,11 @@ describe('util/emoji', () => {
       expect(emojify(':foo: :bar: :bee:')).toBe(':foo: :bar: 🐝');
     });
 
+    it('convert warning shortcode to emoji', () => {
+      const warning = emojify(':warning:');
+      expect(warning).toBe('⚠️');
+    });
+
     it('does not encode when config option is disabled', () => {
       setEmojiConfig({ unicodeEmoji: false });
       expect(emojify('Let it :bee:')).toBe('Let it :bee:');
@@ -54,20 +59,30 @@ describe('util/emoji', () => {
         expect(unemojify(unsupported)).toBe('�');
       });
     });
-  });
 
-  describe('problem characters', () => {
-    it.each(['🚀', '💎', '🧹', '📦'])('converts %s forth and back', (char) => {
+    it('converts warning emoji to shortcode', () => {
       setEmojiConfig({ unicodeEmoji: false });
-      const codified = unemojify(char);
-      expect(codified).not.toEqual(char);
-
-      setEmojiConfig({ unicodeEmoji: true });
-      const emojified = emojify(codified);
-      expect(emojified).toEqual(char);
+      const emoji = '⚠️';
+      const result = unemojify(emoji);
+      expect(result).toBe(':warning:');
     });
   });
 
+  describe('problematic characters', () => {
+    it.each(['🚀', '💎', '🧹', '📦', '⚠️'])(
+      'converts %s forth and back',
+      (char) => {
+        setEmojiConfig({ unicodeEmoji: false });
+        const codified = unemojify(char);
+        expect(codified).not.toEqual(char);
+
+        setEmojiConfig({ unicodeEmoji: true });
+        const emojified = emojify(codified);
+        expect(emojified).toEqual(char);
+      },
+    );
+  });
+
   describe('stripEmojis', () => {
     const makeEmoji = (hexCode: string): string =>
       fromCodepointToUnicode(fromHexcodeToCodepoint(hexCode));
diff --git a/lib/util/emoji.ts b/lib/util/emoji.ts
index 219392ab98..a5e03a8640 100644
--- a/lib/util/emoji.ts
+++ b/lib/util/emoji.ts
@@ -1,4 +1,3 @@
-import is from '@sindresorhus/is';
 import mathiasBynensEmojiRegex from 'emoji-regex';
 import {
   fromCodepointToUnicode,
@@ -12,6 +11,7 @@ import type { RenovateConfig } from '../config/types';
 import dataFiles from '../data-files.generated';
 import { logger } from '../logger';
 import { regEx } from './regex';
+import { Result } from './result';
 import { Json } from './schema-utils';
 
 let unicodeEmoji = true;
@@ -21,27 +21,48 @@ const shortCodesByHex = new Map<string, string>();
 const hexCodesByShort = new Map<string, string>();
 
 const EmojiShortcodesSchema = Json.pipe(
-  z.record(z.string(), z.union([z.string(), z.array(z.string())])),
+  z.record(
+    z.string(),
+    z.union([z.string().transform((val) => [val]), z.array(z.string())]),
+  ),
 );
+type EmojiShortcodeMapping = z.infer<typeof EmojiShortcodesSchema>;
+
+const patchedEmojis: EmojiShortcodeMapping = {
+  '26A0-FE0F': ['warning'], // Colorful warning (⚠️) instead of black and white (⚠)
+};
+
+function initMapping(mapping: EmojiShortcodeMapping): void {
+  for (const [hex, shortcodes] of Object.entries(mapping)) {
+    const mainShortcode = `:${shortcodes[0]}:`;
+
+    shortCodesByHex.set(hex, mainShortcode);
+    shortCodesByHex.set(stripHexCode(hex), mainShortcode);
+
+    for (const shortcode of shortcodes) {
+      hexCodesByShort.set(`:${shortcode}:`, hex);
+    }
+  }
+}
 
 function lazyInitMappings(): void {
   if (!mappingsInitialized) {
-    const result = EmojiShortcodesSchema.safeParse(
-      dataFiles.get('node_modules/emojibase-data/en/shortcodes/github.json')!,
+    const githubShortcodes = dataFiles.get(
+      'node_modules/emojibase-data/en/shortcodes/github.json',
     );
-    // istanbul ignore if: not easily testable
-    if (!result.success) {
-      logger.warn({ error: result.error }, 'Unable to parse emoji shortcodes');
-      return;
-    }
-    for (const [hex, val] of Object.entries(result.data)) {
-      const shortCodes = is.array(val) ? val : [val];
-      shortCodesByHex.set(hex, `:${shortCodes[0]}:`);
-      shortCodes.forEach((shortCode) => {
-        hexCodesByShort.set(`:${shortCode}:`, hex);
-      });
-    }
-    mappingsInitialized = true;
+
+    Result.parse(githubShortcodes, EmojiShortcodesSchema)
+      .onValue((data) => {
+        initMapping(data);
+        initMapping(patchedEmojis);
+        mappingsInitialized = true;
+      })
+      .onError(
+        /* istanbul ignore next */
+        (error) => {
+          logger.warn({ error }, 'Unable to parse emoji shortcodes');
+        },
+      );
   }
 }
 
diff --git a/lib/workers/repository/errors-warnings.spec.ts b/lib/workers/repository/errors-warnings.spec.ts
index e93d556440..4fee652573 100644
--- a/lib/workers/repository/errors-warnings.spec.ts
+++ b/lib/workers/repository/errors-warnings.spec.ts
@@ -85,7 +85,7 @@ describe('workers/repository/errors-warnings', () => {
         "
         ---
 
-        > âš  **Warning**
+        > ⚠️ **Warning**
         > 
         > Some dependencies could not be looked up. Check the Dependency Dashboard for more information.
 
@@ -133,7 +133,7 @@ describe('workers/repository/errors-warnings', () => {
         "
         ---
 
-        > âš  **Warning**
+        > ⚠️ **Warning**
         > 
         > Some dependencies could not be looked up. Check the warning logs for more information.
 
@@ -197,7 +197,7 @@ describe('workers/repository/errors-warnings', () => {
         "
         ---
 
-        > âš  **Warning**
+        > ⚠️ **Warning**
         > 
         > Renovate failed to look up the following dependencies: \`dependency-1\`, \`dependency-2\`.
         > 
@@ -305,7 +305,7 @@ describe('workers/repository/errors-warnings', () => {
         "
         ---
         > 
-        > âš  **Warning**
+        > ⚠️ **Warning**
         > 
         > Please correct - or verify that you can safely ignore - these dependency lookup failures before you merge this PR.
         > 
-- 
GitLab