Skip to content

Commit cfda5c7

Browse files
committed
refactor(core): modernize rule registration and number normalization
1 parent b4624bb commit cfda5c7

File tree

6 files changed

+36
-33
lines changed

6 files changed

+36
-33
lines changed

TTSTextNormalization/Core/TextNormalizationPipeline.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,4 @@ public string Normalize(string? inputText)
138138
_logger?.LogDebug("Normalization complete. Final text: \"{FinalText}\"", currentText);
139139
return currentText;
140140
}
141-
}
141+
}

TTSTextNormalization/DependencyInjection/RuleRegistration.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
using Microsoft.Extensions.DependencyInjection;
1+
using Microsoft.Extensions.DependencyInjection;
2+
using System.Diagnostics.CodeAnalysis;
23
using TTSTextNormalization.Abstractions;
34

45
namespace TTSTextNormalization.DependencyInjection;
56

67
/// <summary>
78
/// Internal record holding registration details for a normalization rule.
89
/// </summary>
9-
public sealed class RuleRegistration
10+
public sealed record RuleRegistration
1011
{
1112
/// <summary>
1213
/// The concrete type of the rule implementation (<see cref="ITextNormalizationRule"/>).
@@ -23,4 +24,18 @@ public sealed class RuleRegistration
2324
/// If null, the rule's default order is used.
2425
/// </summary>
2526
public int? OrderOverride { get; init; }
26-
}
27+
28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="RuleRegistration"/> record.
30+
/// </summary>
31+
/// <param name="ruleType">The concrete rule implementation type.</param>
32+
/// <param name="lifetime">The service lifetime for the rule.</param>
33+
/// <param name="orderOverride">Optional order override for the rule.</param>
34+
[SetsRequiredMembers]
35+
public RuleRegistration(Type ruleType, ServiceLifetime lifetime, int? orderOverride = null)
36+
{
37+
RuleType = ruleType;
38+
Lifetime = lifetime;
39+
OrderOverride = orderOverride;
40+
}
41+
}

TTSTextNormalization/DependencyInjection/TextNormalizationBuilder.cs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,15 @@ namespace TTSTextNormalization.DependencyInjection;
77
/// <summary>
88
/// Default implementation of <see cref="ITextNormalizationBuilder"/>.
99
/// </summary>
10-
internal sealed class TextNormalizationBuilder : ITextNormalizationBuilder
10+
internal sealed class TextNormalizationBuilder(IServiceCollection services) : ITextNormalizationBuilder
1111
{
1212
/// <inheritdoc/>
13-
public IServiceCollection Services { get; }
13+
public IServiceCollection Services { get; } =
14+
services ?? throw new ArgumentNullException(nameof(services));
1415

1516
// Store registration details internally
1617
internal List<RuleRegistration> Registrations { get; } = [];
1718

18-
/// <summary>
19-
/// Initializes a new instance of the <see cref="TextNormalizationBuilder"/> class.
20-
/// </summary>
21-
/// <param name="services">The service collection to configure.</param>
22-
/// <exception cref="ArgumentNullException">Thrown if services is null.</exception>
23-
public TextNormalizationBuilder(IServiceCollection services)
24-
{
25-
ArgumentNullException.ThrowIfNull(services);
26-
Services = services;
27-
}
28-
2919
/// <inheritdoc/>
3020
public ITextNormalizationBuilder AddRule<T>(
3121
ServiceLifetime lifetime = ServiceLifetime.Singleton,
@@ -39,13 +29,8 @@ public ITextNormalizationBuilder AddRule<T>(
3929
// 2. Record the registration details (including the override) for the pipeline.
4030
// We allow multiple registrations if needed, although the pipeline
4131
// will likely resolve only one instance per type unless configured differently.
42-
Registrations.Add(new RuleRegistration
43-
{
44-
RuleType = typeof(T),
45-
Lifetime = lifetime,
46-
OrderOverride = orderOverride
47-
});
32+
Registrations.Add(new RuleRegistration(typeof(T), lifetime, orderOverride));
4833

4934
return this;
5035
}
51-
}
36+
}

TTSTextNormalization/Rules/AbbreviationNormalizationRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public AbbreviationNormalizationRule(IOptions<AbbreviationRuleOptions> optionsAc
122122
public string Apply(string inputText)
123123
{
124124
ArgumentNullException.ThrowIfNull(inputText);
125-
if (string.IsNullOrEmpty(inputText) || _effectiveAbbreviations.Count == 0)
125+
if (inputText.Length == 0 || _effectiveAbbreviations.Count == 0)
126126
return inputText;
127127

128128
string currentText = inputText;

TTSTextNormalization/Rules/EmojiNormalizationRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,4 @@ private string EmojiMatchEvaluator(Match match)
9999
return match.Value;
100100
}
101101
}
102-
}
102+
}

TTSTextNormalization/Rules/NumberNormalizationRule.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ public sealed partial class NumberNormalizationRule : ITextNormalizationRule
1818
private const int RegexTimeoutMilliseconds = 150;
1919

2020
// Keep DigitWords for the new multi-dot logic
21-
private static readonly string[] DigitWords = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
21+
private static readonly string[] DigitWords =
22+
["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
2223

2324
/// <summary>
2425
/// Initializes a new instance of the <see cref="NumberNormalizationRule"/> class.
@@ -29,7 +30,7 @@ public NumberNormalizationRule() { }
2930
public string Apply(string inputText)
3031
{
3132
ArgumentNullException.ThrowIfNull(inputText);
32-
if (string.IsNullOrEmpty(inputText))
33+
if (inputText.Length == 0)
3334
return inputText;
3435

3536
string currentText = inputText;
@@ -121,10 +122,12 @@ private static string CardinalDecimalMatchEvaluator(Match match)
121122
builder.Append(integerWords).Append(" point");
122123
foreach (char digitChar in fractionPartStr)
123124
{
124-
if (int.TryParse(digitChar.ToString(), out int digitValue) && digitValue >= 0 && digitValue <= 9)
125-
{ builder.Append(' ').Append(DigitWords[digitValue]); }
126-
else
127-
{ return match.Value; }
125+
if (digitChar is < '0' or > '9')
126+
{
127+
return match.Value;
128+
}
129+
130+
builder.Append(' ').Append(DigitWords[digitChar - '0']);
128131
}
129132

130133
return $" {builder} ";
@@ -154,4 +157,4 @@ private static string CardinalDecimalMatchEvaluator(Match match)
154157
// simpler integers or single-dot decimals.
155158
[GeneratedRegex(@"(?<![\p{L}\p{N}-])(?<integer>\d+)(?:\.(?<fraction>\d+))?(?![\p{L}\p{N}-])", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant, RegexTimeoutMilliseconds)]
156159
private static partial Regex CardinalDecimalNumberRegex();
157-
}
160+
}

0 commit comments

Comments
 (0)