diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 9357a3adc93844..a0873b7d0c09b6 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 97e9c9309bc1eb..9dc475a838ae05 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 219392ab98b77d..a5e03a86409cac 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(); const hexCodesByShort = new Map(); 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; + +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 e93d5564400098..4fee6525739f7e 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. >