@@ -73,6 +73,11 @@ protected static function registerDefaultStyles(ConsoleOutput $output): void
7373 'success_header ' => ['bright-white ' , 'green ' , ['bold ' ]],
7474 'info_header ' => ['bright-white ' , 'cyan ' , ['bold ' ]],
7575
76+ // generic formatting helpers
77+ 'bold ' => [null , null , ['bold ' ]],
78+ 'underline ' => [null , null , ['underscore ' ]],
79+ 'dim ' => ['gray ' , null , []],
80+
7681 // extras
7782 'yellow ' => ['yellow ' , null , ['bold ' ]],
7883 'green ' => ['green ' , null , ['bold ' ]],
@@ -109,9 +114,13 @@ public static function addStyle(string $name, string $foreground, ?string $backg
109114
110115 /**
111116 * Generic write with optional STDERR target.
117+ * Supports common aliases like <bold>, <b>, <strong>, <i>, <em>, <u>, <underline>, <dim>.
112118 */
113119 public static function writeln (string $ message , bool $ stderr = false ): void
114120 {
121+ // Normalize popular formatting tags to Symfony Console-supported tags
122+ $ message = static ::normalizeFormatting ($ message );
123+
115124 $ out = static ::getOutput ();
116125 $ target = $ stderr ? $ out ->getErrorOutput () : $ out ;
117126 $ target ->writeln ($ message );
@@ -140,6 +149,37 @@ public static function segments(array $segments, string $separator = ''): string
140149 return implode ($ separator , $ parts );
141150 }
142151
152+ /**
153+ * Normalize common/alias formatting tags to supported console styles.
154+ * - Maps: <b>, <strong>, <bold> => <bold>
155+ * <u>, <underline> => <underline>
156+ * <dim> => <dim>
157+ * - Strips unsupported emphasis tags like <i>, <em> (keeps content).
158+ */
159+ protected static function normalizeFormatting (string $ message ): string
160+ {
161+ $ map = [
162+ 'b ' => 'bold ' ,
163+ 'strong ' => 'bold ' ,
164+ 'bold ' => 'bold ' ,
165+ 'u ' => 'underline ' ,
166+ 'underline ' => 'underline ' ,
167+ 'dim ' => 'dim ' ,
168+ ];
169+
170+ foreach ($ map as $ from => $ to ) {
171+ // Opening tags
172+ $ message = preg_replace ('/<\s* ' . $ from . '\s*>/i ' , '< ' . $ to . '> ' , $ message );
173+ // Closing tags
174+ $ message = preg_replace ('/<\s*\/\s* ' . $ from . '\s*>/i ' , '</ ' . $ to . '> ' , $ message );
175+ }
176+
177+ // Remove unsupported tags but keep their content
178+ $ message = preg_replace ('/<\s*\/?\s*(i|em)\s*>/i ' , '' , $ message );
179+
180+ return $ message ;
181+ }
182+
143183 /**
144184 * Print a group/section header (e.g., a namespace or package name).
145185 * Accepts optional style/color while keeping backward compatibility.
0 commit comments