33namespace Tempest \Intl \MessageFormat \Formatter ;
44
55use Tempest \Intl \MessageFormat \FormattingFunction ;
6+ use Tempest \Intl \MessageFormat \MarkupFormatter ;
67use Tempest \Intl \MessageFormat \Parser \Node \ComplexBody \ComplexBody ;
78use Tempest \Intl \MessageFormat \Parser \Node \ComplexBody \Matcher ;
89use Tempest \Intl \MessageFormat \Parser \Node \ComplexBody \SimplePatternBody ;
1314use Tempest \Intl \MessageFormat \Parser \Node \Expression \FunctionCall ;
1415use Tempest \Intl \MessageFormat \Parser \Node \Expression \FunctionExpression ;
1516use Tempest \Intl \MessageFormat \Parser \Node \Expression \LiteralExpression ;
17+ use Tempest \Intl \MessageFormat \Parser \Node \Expression \Option ;
1618use Tempest \Intl \MessageFormat \Parser \Node \Expression \VariableExpression ;
1719use Tempest \Intl \MessageFormat \Parser \Node \Key \WildcardKey ;
1820use Tempest \Intl \MessageFormat \Parser \Node \Literal \Literal ;
2830use Tempest \Intl \MessageFormat \Parser \Node \Variable ;
2931use Tempest \Intl \MessageFormat \Parser \Parser ;
3032use Tempest \Intl \MessageFormat \SelectorFunction ;
33+ use Tempest \Intl \MessageFormat \StandaloneMarkupFormatter ;
34+ use Tempest \Support \Arr ;
3135
3236use function Tempest \Support \arr ;
3337
@@ -37,8 +41,10 @@ final class MessageFormatter
3741 private array $ variables = [];
3842
3943 public function __construct (
40- /** @var FormattingFunction[] */
44+ /** @var array< FormattingFunction|SelectorFunction> */
4145 private readonly array $ functions = [],
46+ /** @var array<MarkupFormatter|StandaloneMarkupFormatter> */
47+ private readonly array $ markupFormatters = [],
4248 ) {}
4349
4450 /**
@@ -273,28 +279,6 @@ private function evaluateExpression(Expression $expression): FormattedValue
273279 return new FormattedValue ($ value , $ formatted );
274280 }
275281
276- private function getSelectorFunction (?string $ name ): ?SelectorFunction
277- {
278- if (! $ name ) {
279- return null ;
280- }
281-
282- return arr ($ this ->functions )
283- ->filter (fn (FormattingFunction |SelectorFunction $ fn ) => $ fn instanceof SelectorFunction)
284- ->first (fn (SelectorFunction $ fn ) => $ fn ->name === $ name );
285- }
286-
287- private function getFormattingFunction (?string $ name ): ?FormattingFunction
288- {
289- if (! $ name ) {
290- return null ;
291- }
292-
293- return arr ($ this ->functions )
294- ->filter (fn (FormattingFunction |SelectorFunction $ fn ) => $ fn instanceof FormattingFunction)
295- ->first (fn (FormattingFunction $ fn ) => $ fn ->name === $ name );
296- }
297-
298282 private function evaluateOptions (array $ options ): array
299283 {
300284 $ result = [];
@@ -338,15 +322,69 @@ private function parseLocalVariables(array $variables): array
338322
339323 private function formatMarkup (Markup $ markup ): string
340324 {
341- // TODO: more advanced with options
342- // built-in HtmlMarkup
343325 $ tag = (string ) $ markup ->identifier ;
326+ $ options = Arr \map_with_keys ($ markup ->options , fn (Option $ option ) => yield $ option ->identifier ->name => $ option ->value ->value );
327+
328+ if ($ markup ->type === MarkupType::STANDALONE ) {
329+ if (is_null ($ formatter = $ this ->getStandaloneMarkupFormatter ($ tag ))) {
330+ return '' ;
331+ }
332+
333+ return $ formatter ->format ($ tag , $ options );
334+ }
335+
336+ if (is_null ($ formatter = $ this ->getMarkupFormatter ($ tag ))) {
337+ return '' ;
338+ }
344339
345340 return match ($ markup ->type ) {
346- MarkupType::OPEN => "< {$ tag }> " ,
347- MarkupType::CLOSE => "</ {$ tag }> " ,
348- MarkupType::STANDALONE => "< {$ tag }/> " ,
341+ MarkupType::OPEN => $ formatter ->formatOpenTag ($ tag , $ options ),
342+ MarkupType::CLOSE => $ formatter ->formatCloseTag ($ tag ),
349343 default => '' ,
350344 };
351345 }
346+
347+ private function getMarkupFormatter (?string $ tag ): ?MarkupFormatter
348+ {
349+ if (! $ tag ) {
350+ return null ;
351+ }
352+
353+ return arr ($ this ->markupFormatters )
354+ ->filter (fn (MarkupFormatter |StandaloneMarkupFormatter $ fn ) => $ fn instanceof MarkupFormatter)
355+ ->first (fn (MarkupFormatter $ fn ) => $ fn ->supportsTag ($ tag ));
356+ }
357+
358+ private function getStandaloneMarkupFormatter (?string $ tag ): ?StandaloneMarkupFormatter
359+ {
360+ if (! $ tag ) {
361+ return null ;
362+ }
363+
364+ return arr ($ this ->markupFormatters )
365+ ->filter (fn (MarkupFormatter |StandaloneMarkupFormatter $ fn ) => $ fn instanceof StandaloneMarkupFormatter)
366+ ->first (fn (StandaloneMarkupFormatter $ fn ) => $ fn ->supportsTag ($ tag ));
367+ }
368+
369+ private function getSelectorFunction (?string $ name ): ?SelectorFunction
370+ {
371+ if (! $ name ) {
372+ return null ;
373+ }
374+
375+ return arr ($ this ->functions )
376+ ->filter (fn (FormattingFunction |SelectorFunction $ fn ) => $ fn instanceof SelectorFunction)
377+ ->first (fn (SelectorFunction $ fn ) => $ fn ->name === $ name );
378+ }
379+
380+ private function getFormattingFunction (?string $ name ): ?FormattingFunction
381+ {
382+ if (! $ name ) {
383+ return null ;
384+ }
385+
386+ return arr ($ this ->functions )
387+ ->filter (fn (FormattingFunction |SelectorFunction $ fn ) => $ fn instanceof FormattingFunction)
388+ ->first (fn (FormattingFunction $ fn ) => $ fn ->name === $ name );
389+ }
352390}
0 commit comments