1+ /**
2+ * Emoji Utilities - Noto Color Emoji System
3+ * Provides consistent emoji display across all platforms using Google Fonts
4+ */
5+
6+ class EmojiUtils {
7+ constructor ( ) {
8+ // Comprehensive emoji mappings with fallbacks
9+ this . emojiMappings = {
10+ // Analytics and Statistics
11+ chart : { emoji : '📊' , text : 'STATS' } ,
12+ thermometer : { emoji : '🌡️' , text : 'HEAT' } ,
13+
14+ // Fuel Types
15+ fuel : { emoji : '⛽' , text : 'FUEL' } ,
16+ truck : { emoji : '🚛' , text : 'DIESEL' } ,
17+ diamond : { emoji : '💎' , text : 'SUPER' } ,
18+ dieselSuper : { emoji : '🚛💎' , text : 'D+' } ,
19+
20+ // Status and Quality
21+ star : { emoji : '⭐' , text : 'GOOD' } ,
22+ trophy : { emoji : '🏆' , text : 'BEST' } ,
23+ warning : { emoji : '⚠️' , text : 'WARN' } ,
24+ target : { emoji : '🎯' , text : 'OK' } ,
25+
26+ // Actions and Tools
27+ money : { emoji : '💰' , text : 'SAVE' } ,
28+ search : { emoji : '🔍' , text : 'FIND' } ,
29+ bulb : { emoji : '💡' , text : 'TIP' } ,
30+ location : { emoji : '📍' , text : 'LOC' } ,
31+
32+ // Trends
33+ trendUp : { emoji : '📈' , text : 'UP' } ,
34+ trendDown : { emoji : '📉' , text : 'DOWN' } ,
35+ trendFlat : { emoji : '➡️' , text : 'SAME' } ,
36+
37+ // UI Elements
38+ mobile : { emoji : '📱' , text : 'APP' } ,
39+ close : { emoji : '✕' , text : 'X' } ,
40+
41+ // System and Performance
42+ trash : { emoji : '🗑️' , text : 'DEL' } ,
43+ refresh : { emoji : '🔄' , text : 'SYNC' } ,
44+ rocket : { emoji : '🚀' , text : 'GO' } ,
45+
46+ // Additional fuel types
47+ fire : { emoji : '🔥' , text : 'LPG' }
48+ } ;
49+
50+ // Ensure Noto Color Emoji CSS is loaded
51+ this . ensureEmojiStyles ( ) ;
52+ }
53+
54+ /**
55+ * Ensure emoji styles are loaded in the document
56+ */
57+ ensureEmojiStyles ( ) {
58+ if ( document . getElementById ( 'emoji-utils-styles' ) ) return ;
59+
60+ const style = document . createElement ( 'style' ) ;
61+ style . id = 'emoji-utils-styles' ;
62+ style . textContent = `
63+ /* Noto Color Emoji font stack for consistent display */
64+ .noto-emoji, .emoji {
65+ font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", "Twemoji Mozilla", emoji, sans-serif !important;
66+ font-style: normal !important;
67+ font-weight: normal !important;
68+ text-rendering: optimizeLegibility !important;
69+ -webkit-font-feature-settings: "liga" off !important;
70+ font-feature-settings: "liga" off !important;
71+ display: inline-block;
72+ vertical-align: middle;
73+ line-height: 1;
74+ }
75+
76+ /* Console and log emoji styling */
77+ .console-emoji {
78+ font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", emoji, monospace !important;
79+ }
80+ ` ;
81+ document . head . appendChild ( style ) ;
82+ }
83+
84+ /**
85+ * Get emoji with proper Noto Color Emoji styling
86+ */
87+ getEmoji ( key , options = { } ) {
88+ const mapping = this . emojiMappings [ key ] ;
89+ if ( ! mapping ) return options . fallback || '•' ;
90+
91+ const {
92+ size = 16 ,
93+ className = 'noto-emoji' ,
94+ inline = true ,
95+ fallbackToText = false
96+ } = options ;
97+
98+ if ( fallbackToText && ! this . supportsColorEmoji ( ) ) {
99+ return `<span class="emoji-text-fallback" style="font-size: ${ size } px;">[${ mapping . text } ]</span>` ;
100+ }
101+
102+ const style = `font-size: ${ size } px; ${ inline ? 'display: inline-block; vertical-align: middle;' : '' } ` ;
103+ return `<span class="${ className } " style="${ style } ">${ mapping . emoji } </span>` ;
104+ }
105+
106+ /**
107+ * Get plain emoji character (for console logs, etc.)
108+ */
109+ getPlainEmoji ( key ) {
110+ const mapping = this . emojiMappings [ key ] ;
111+ return mapping ? mapping . emoji : '•' ;
112+ }
113+
114+ /**
115+ * Create emoji element
116+ */
117+ createElement ( key , options = { } ) {
118+ const mapping = this . emojiMappings [ key ] ;
119+ if ( ! mapping ) return null ;
120+
121+ const {
122+ size = 16 ,
123+ className = 'noto-emoji'
124+ } = options ;
125+
126+ const span = document . createElement ( 'span' ) ;
127+ span . className = className ;
128+ span . textContent = mapping . emoji ;
129+ span . style . cssText = `
130+ font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", emoji, sans-serif;
131+ font-size: ${ size } px;
132+ display: inline-block;
133+ vertical-align: middle;
134+ line-height: 1;
135+ font-style: normal;
136+ font-weight: normal;
137+ text-rendering: optimizeLegibility;
138+ -webkit-font-smoothing: antialiased;
139+ -moz-osx-font-smoothing: grayscale;
140+ ` ;
141+
142+ return span ;
143+ }
144+
145+ /**
146+ * Replace emoji placeholders in text
147+ */
148+ replaceEmojiPlaceholders ( text ) {
149+ return text . replace ( / : ( \w + ) : / g, ( match , key ) => {
150+ const mapping = this . emojiMappings [ key ] ;
151+ return mapping ? mapping . emoji : match ;
152+ } ) ;
153+ }
154+
155+ /**
156+ * Check if browser supports color emoji
157+ */
158+ supportsColorEmoji ( ) {
159+ if ( this . emojiSupport !== undefined ) {
160+ return this . emojiSupport ;
161+ }
162+
163+ try {
164+ const canvas = document . createElement ( 'canvas' ) ;
165+ canvas . width = 20 ;
166+ canvas . height = 20 ;
167+ const ctx = canvas . getContext ( '2d' ) ;
168+
169+ if ( ! ctx ) {
170+ this . emojiSupport = false ;
171+ return false ;
172+ }
173+
174+ ctx . fillStyle = '#000' ;
175+ ctx . textBaseline = 'middle' ;
176+ ctx . textAlign = 'center' ;
177+ ctx . font = '16px "Noto Color Emoji"' ;
178+ ctx . fillText ( '🎨' , 10 , 10 ) ;
179+
180+ const imageData = ctx . getImageData ( 0 , 0 , 20 , 20 ) ;
181+ const hasColor = imageData . data . some ( ( channel , i ) =>
182+ i % 4 < 3 && channel !== 0 && channel !== 255
183+ ) ;
184+
185+ this . emojiSupport = hasColor ;
186+ return this . emojiSupport ;
187+ } catch ( e ) {
188+ this . emojiSupport = false ;
189+ return false ;
190+ }
191+ }
192+
193+ /**
194+ * Get all available emoji keys
195+ */
196+ getAvailableEmojis ( ) {
197+ return Object . keys ( this . emojiMappings ) ;
198+ }
199+ }
200+
201+ // Global instance
202+ window . emojiUtils = new EmojiUtils ( ) ;
203+
204+ // Export for module usage
205+ if ( typeof module !== 'undefined' && module . exports ) {
206+ module . exports = EmojiUtils ;
207+ }
0 commit comments