SmartFormat.NET
3.0.0-alpha.4
Prefix Reserved
See the version list below for details.
dotnet add package SmartFormat.NET --version 3.0.0-alpha.4
NuGet\Install-Package SmartFormat.NET -Version 3.0.0-alpha.4
<PackageReference Include="SmartFormat.NET" Version="3.0.0-alpha.4" />
paket add SmartFormat.NET --version 3.0.0-alpha.4
#r "nuget: SmartFormat.NET, 3.0.0-alpha.4"
// Install SmartFormat.NET as a Cake Addin #addin nuget:?package=SmartFormat.NET&version=3.0.0-alpha.4&prerelease // Install SmartFormat.NET as a Cake Tool #tool nuget:?package=SmartFormat.NET&version=3.0.0-alpha.4&prerelease
What's new in v3.0.0-alpha.4
(compared to v2.7.1)
1. Significant boost in performance
After implementing a zero allocation ValueStringBuilder
based on ZString with #193:
- Parsing is 10% faster with 50-80% less GC and memory allocation
- Formatting is up to 40% faster with 50% less GC and memory allocation
More optimizations:
ReflectionSource
- Added a type cache which increases speed by factor 4. Thanks to @karljj1. (#155).
- Type caching can be disabled (#217)
- Dictionary for type cache changed to
ConcurrentDictionary
(#217) TypeCache
is accessible from a derived class (#217)
DictionarySource
- Speed increased by 10% with less GC pressure (#189)
2. Exact control of whitespace text output
This was an issue in v2 and was going back to combining string.Format
compatibility with Smart.Format features. This is resolved by setting the desired mode with SmartSettings.StringFormatCompatibility
(defaults to false
). (#172)
3. Literals may contain any Unicode characters (#166)
Add unicode escape characters like "\u1234"
. Thanks to @karljj1.
4. Separate modes for "Smart.Format features" and "string.Format
compatibility"
The mode can be set with SmartSettings.StringFormatCompatibility
. By default, SmartSettings.StringFormatCompatibility
is false
. (#173, #175)
a) Smart.Format features mode
- Brings the full set of features implemented in Smart.Format
- Curly braces are escaped the Smart.Format way with
\{
and\}
. - As long as special characters
(){}:\
are escaped with\
, any character is allowed anywhere. Note: This applies also for the colon.
b) string.Format
compatibility mode
- SmartFormat acts as a drop-in replacement
- On top, it allows for named placeholders besides indexed placeholders.
- The
Parser
will not include the formatter name or formatting options. Like withstring.Format
, everything after theSelector
separator (colon) is considered as format specifier. - Curly braces are escaped the
string.Format
way with{{
and}}
. This is the reason for all limitations instring.Format
compatibility mode DefaultFormatter
is the only formatter which will be invoked.null
will be output asstring.Empty
.
5. Unlimited characters in formatter options (#164, #165)
This was a big limitation in v2. In v3, the Parser
can parse any character as part of formatter options. This means e.g. no limitations for RegEx
expressions used in IsMatchFormatter
. Note: Special characters like (){}:\
must be escaped with \
.
Say we want to include in the output, whether an email is valid (simplified):
var emailRegEx = "^((\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)\s*[;]{0,1}\s*)+$";
// ask a little helper to escape the RegEx
var escaped = EscapedLiteral.EscapeCharLiterals('\\', emailRegEx, 0, emailRegEx.Length, true);
// insert the escaped literal from the helper
var result = Smart.Format("Email {0:ismatch("^\(\(\\w+\([-+.]\\w+\)*@\\w+\([-.]\\w+\)*\\.\\w+\([-.]\\w+\)*\)\\s*[;]\{0,1\}\\s*\)+$"):{} is valid|{} NOT valid}", "joe@specimen.com");
// returns "Email joe@specimen.com is valid"
6. Simplified caching of parser result (#183)
"Parse once, format often" is simplified: The Parser
's Format
result can be directly used as a parameter of the SmartFormatter
.
var temperatures = new[] {-20, -10, -15};
// parse once
var parsedFormat = new Parser().ParseFormat("Temperature is {Temp}°.");
// one SmartFormatter instance
var formatter = Smart.CreateDefaultSmartFormat();
foreach (var current in temperatures)
{
var result = formatter.Format(parsedFormat, new {Temp = current});
}
This pattern is much faster than calling
// combined parsing and formatting
var result = Smart.Format("Temperature at North Pole is {Temp}°.", new {Temp = current});
in the foreach loop.
Class FormatCache
has been removed in v3.
7. Global support for Alignment (#174)
In v2, Alignment of output values was limited to the DefaultFormatter
. It's about the equivalent to e.g. string.Format("{0,10}")
.
- Alignment is now supported by all
IFormatter
s. - Introduced
FormatterSettings.AlignmentFillCharacter
, to customize the the fill character. Default is space (0x20), like withstring.Format
. - Modified
ListFormatter
so that items can be aligned (but the spacers stay untouched).
8. Added StringSource
as another ISource
(#178, #216)
The StringSource
takes over functionality, which have been implemented in ReflectionSource
in v2. Compared to reflection caching, speed is 20% better at 25% less memory allocation.
StringSource
brings the following built-in methods (as selector names):
- Length
- ToUpper
- ToUpperInvariant
- ToLower
- ToLowerInvariant
- Trim
- TrimStart
- TrimEnd
- ToCharArray
- Capitalize
- CapitalizeWords
- FromBase64
- ToBase64
All these selector names may be linked. Example with an indexed placeholder:
Smart.Format("{0.ToLower.TrimStart.TrimEnd.ToBase64}", " ABCDE ");
// result: "YWJjZGU="
9. Introduced Nullable Notation (#176)
C# like nullable
notation allows to display Nullable<T>
types.
The Smart.Format notation is "{SomeNullable?.Property}"
. If SomeNullable
is null, the expression is evaluated as string.Empty
.
The nullable operator can also be used for evaluating a list index. E.g.: Smart.Format("{TheList?[1]}")
will output string.Empty
, if the list variable is null.
Note: Trying to evaluate null
without the nullable operator will result in a formatting exception. This is the same behavior as in v2.
All Format()
methods accept nullable args (#196).
Opposed to string.Format
null(able) arguments are allowed.
10. Added NullFormatter
(#176, #199)
In the context of Nullable Notation, the NullFormatter
has been added. It outputs a custom string literal, if the variable is null
, else another literal (default is string.Empty
) or Placeholder
.
Example:
Smart.Format("{TheValue:isnull:This value is null}", new {TheValue = null});
// Result: "This value is null"
Smart.Format("{TheValue:isnull:The value is null|The value is {}}", new {TheValue = 1234});
// Result: "The value is 1234"
11. Added LocalizationFormatter
(#176
Features
- Added
LocalizationFormatter
to localize literals and placeholders - Added
ILocalizationProvider
and a standard implemention asLocalizationProvider
, which handlesresx
resource files. A fallback culture can be set. It will be used, in case no item for a certain culture could be found in any of the resources.LocalizationProvider
can search an unlimited number of defined resoures. SmartSettings
were exended with categoryLocalization
. That way, customIFormatter
s can also make use of localization, if needed.- Added
LocalizationFormattingException
, which is derived fromFormattingException
to easily identify this kind of issues
Examples
Culture-specific results shown here are included in embedded resource files, which are omitted for brevity.
- Localize pure literals into Spanish:
// culture supplied as a format option
_ = Smart.Format(culture, "{:L(en):WeTranslateText}");
// culture supplied as an argument to the formatter
var culture = CultureInfo.GetCultureInfo("es");
_ = Smart.Format(culture, "{:L:WeTranslateText}");
// result for both: "Traducimos el texto"
- Localized strings may contain placeholders
_ = Smart.Format("{0} {1:L(es):has {:#,#} inhabitants}", "X-City", 8900000);
// result: "X-City tiene 8.900.000 habitantes"
_ = Smart.Format("{0} {1:L(es):has {:#,#} inhabitants}", "X-City", 8900000);
// result: "X-City has 8,900,000 inhabitants"
- Localization can be used together with other formatters
_ = Smart.Format("{0:plural:{:L(en):{} item}|{:L(en):{} items}}", 0;
// result for English: 0 items
_ = Smart.Format("{0:plural:{:L(fr):{} item}|{:L(fr):{} items}}", 0;
// result for French: 0 élément
_ = Smart.Format("{0:plural:{:L(fr):{} item}|{:L(fr):{} items}}", 200;
// result for French: 200 éléments
12. Improved custom ISource
and IFormatter
implementations (#180)
Any custom exensions can implement IInitializer
. Then, the SmartFormatter
will call Initialize(SmartFormatter smartFormatter)
of the extension, before adding it to the extension list.
13. IFormatter
s have one single, unique name (#185)
In v2, IFormatter
s could have an unlimited number of names.
To improve performance, in v3, this is limited to one single, unique name.
14. JSON support (#177, #201)
Separation of JsonSource
into 2 ISource
extensions:
NewtonSoftJsonSource
SystemTextJsonSource
Fix: NewtonSoftJsonSource
handles null
values correctly (#201)
15. SmartFormatter
takes IList<object>
parameters
Added support for IList<object>
parameters to the SmartFormatter
(thanks to @karljj1) (#154)
16. SmartObjects
have been removed
- Removed obsolete
SmartObjects
(which have been replaced byValueTuple
) (092b7b1
)
17. Improved parsing of HTML input (#203)
Introduced experimental bool ParserSettings.ParseInputAsHtml
.
The default is false
.
If true
, theParser
will parse all content inside <script> and <style> tags as LiteralText
. All other places may still contain Placeholder
s.
This is because <script> and <style> tags may contain curly or square braces, that interfere with the SmartFormat {Placeholder
}.
Best results can only be expected with clean HTML: balanced opening and closing tags, single and double quotes. Also, do not use angle brackets, single and double quotes in script or style comments.
SmartFormat is not a fully-fledged HTML parser. If this is required, use AngleSharp or HtmlAgilityPack.
18. Refactored PluralLocalizationFormatter
(#209)
- Constructor with string argument for default language is obsolete.
- Property
DefaultTwoLetterISOLanguageName
is obsolete. - Culture is now determined in this sequence (same as with
LocalizationFormatter
):<br/>- Get the culture from the
FormattingInfo.FormatterOptions
.<br/> - Get the culture from the
IFormatProvider
argument (which may be aCultureInfo
) toSmartFormatter.Format(IFormatProvider, string, object?[])
<br/> - The
CultureInfo.CurrentUICulture
<br/>
- Get the culture from the
19. Refactored TimeFormatter
(#220, #221)
- Constructor with string argument for default language is obsolete.
- Property
DefaultTwoLetterISOLanguageName
is obsolete. - Culture is now determined in this sequence (same as with
LocalizationFormatter
andPluralLocalizationFormatter
):<br/>- Get the culture from the
FormattingInfo.FormatterOptions
.<br/> - Get the culture from the
IFormatProvider
argument (which may be aCultureInfo
) toSmartFormatter.Format(IFormatProvider, string, object?[])
<br/> - The
CultureInfo.CurrentUICulture
<br/>
- Get the culture from the
- New: With the extended
CommonLanguagesTimeTextInfo
,TimeFormatter
includes French, Spanish, Portuguese, Italian and German as new languages besides English out-of-the-box. - New: With e.g.
TimeFormatter.FallbackLanguage = "en";
, this fallback language will be used, if no supported language could be found. - New: Custom languages can now easily be added to
CommonLanguagesTimeTextInfo
. Custom languages override built-in definitions.var language = "nl"; // dummy - it's English, not Dutch ;-) TimeTextInfo custom = new( pluralRule: PluralRules.GetPluralRule(language), week: new[] { "{0} week", "{0} weeks" }, day: new[] { "{0} day", "{0} days" }, hour: new[] { "{0} hour", "{0} hours" }, minute: new[] { "{0} minute", "{0} minutes" }, second: new[] { "{0} second", "{0} seconds" }, millisecond: new[] { "{0} millisecond", "{0} milliseconds" }, w: new[] { "{0}w" }, d: new[] { "{0}d" }, h: new[] { "{0}h" }, m: new[] { "{0}m" }, s: new[] { "{0}s" }, ms: new[] { "{0}ms" }, lessThan: "less than {0}"); CommonLanguagesTimeTextInfo.AddLanguage(language, custom)
- Changed:
- This notation - using formats as formatter options - was allowed in Smart.Format v2.x, but is now depreciated. It is still detected and working, as long as the format part is left empty
var formatDepreciated = "{0:time(abbr hours noless)}";
- This format string is recommended for Smart.Format v3 and later. It allows for including the language as an option to the
TimeFormatter
:
// Without language option: var formatRecommended = "{0:time:abbr hours noless:}"; // With language option: var formatRecommended = "{0:time(en):abbr hours noless:}";
- PRs for extending built-in languages are welcome.
- Example:
var timeSpan = new TimeSpan(1,1,1,1,1) Smart.Format("{0:time(en):hours minutes}", timeSpan); // result: "25 hours 1 minute" Smart.Format("{0:time(fr):hours minutes}", timeSpan); // result: "25 heures 1 minute"
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 is compatible. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.6.1
- Newtonsoft.Json (>= 12.0.3)
- System.Memory (>= 4.5.4)
- System.Text.Json (>= 4.7.2)
- System.ValueTuple (>= 4.5.0)
-
.NETStandard 2.0
- Newtonsoft.Json (>= 12.0.3)
- System.Memory (>= 4.5.4)
- System.Text.Json (>= 4.7.2)
- System.ValueTuple (>= 4.5.0)
-
.NETStandard 2.1
- Newtonsoft.Json (>= 12.0.3)
- System.Memory (>= 4.5.4)
- System.Text.Json (>= 4.7.2)
- System.ValueTuple (>= 4.5.0)
NuGet packages (71)
Showing the top 5 NuGet packages that depend on SmartFormat.NET:
Package | Downloads |
---|---|
Takenet.MessagingHub.Client
The C# SDK for the Messaging Hub |
|
Take.Elephant
Elephant storage library |
|
Take.Blip.Client
BLiP C# client |
|
Takenet.Elephant
Elephant storage library |
|
Cogniteam.Nimbus.Core
Package Description |
GitHub repositories (11)
Showing the top 5 popular GitHub repositories that depend on SmartFormat.NET:
Repository | Stars |
---|---|
canton7/SyncTrayzor
Windows tray utility / filesystem watcher / launcher for Syncthing
|
|
snatch-dev/Convey
A simple recipe for .NET Core microservices.
|
|
dukus/digiCamControl
DSLR camera remote control open source software
|
|
XAMLMarkupExtensions/WPFLocalizeExtension
LocalizationExtension is a the easy way to localize any type of DependencyProperties or native Properties on DependencyObjects
|
|
fernandreu/office-ribbonx-editor
An overhauled fork of the original Custom UI Editor for Microsoft Office, built with WPF
|
Version | Downloads | Last updated |
---|---|---|
3.5.1 | 13,741 | 10/11/2024 |
3.5.0 | 98,773 | 7/29/2024 |
3.4.0 | 83,260 | 5/15/2024 |
3.3.2 | 238,609 | 1/29/2024 |
3.3.1 | 33,447 | 1/14/2024 |
3.3.0 | 189,826 | 9/25/2023 |
3.2.2 | 81,168 | 8/3/2023 |
3.2.1 | 391,941 | 2/19/2023 |
3.2.0 | 406,408 | 9/18/2022 |
3.1.0 | 431,156 | 5/17/2022 |
3.0.0 | 194,925 | 3/14/2022 |
3.0.0-rc.2 | 3,164 | 2/15/2022 |
3.0.0-rc.1 | 1,867 | 2/1/2022 |
3.0.0-alpha.5 | 1,173 | 12/3/2021 |
3.0.0-alpha.4 | 1,819 | 10/25/2021 |
3.0.0-alpha.3 | 1,033 | 9/20/2021 |
3.0.0-alpha.2 | 743 | 9/5/2021 |
3.0.0-alpha.1 | 2,928 | 8/29/2021 |
2.7.3 | 402,953 | 6/28/2022 |
2.7.2 | 365,384 | 12/26/2021 |
2.7.1 | 306,905 | 10/21/2021 |
2.7.0 | 1,321,466 | 4/10/2021 |
2.6.2 | 354,491 | 2/17/2021 |
2.6.1 | 10,195 | 2/12/2021 |
2.5.3 | 984,301 | 11/10/2020 |
2.5.3-preview1 | 4,386 | 11/2/2020 |
2.5.2 | 379,843 | 6/16/2020 |
2.5.1 | 17,193 | 6/9/2020 |
2.5.0 | 815,787 | 11/2/2019 |
2.4.2 | 1,248,506 | 2/9/2019 |
2.4.1 | 55,337 | 1/5/2019 |
2.4.0 | 28,147 | 1/4/2019 |
2.3.1.1 | 178,603 | 11/15/2018 |
2.3.0 | 798,672 | 6/13/2018 |
2.2.0 | 164,508 | 2/17/2018 |
2.1.0.2 | 1,087,662 | 8/15/2017 |
2.1.0.1 | 576,943 | 6/27/2017 |
2.0.0 | 433,204 | 12/4/2016 |
1.7.1.1 | 16,646 | 11/28/2016 |
1.6.1 | 143,230 | 3/4/2015 |
1.6.0 | 5,737 | 3/4/2015 |
1.5.0 | 5,702 | 2/12/2015 |
1.4.0 | 4,233 | 2/12/2015 |
1.3.0 | 4,193 | 2/12/2015 |
1.2.0 | 8,728 | 2/7/2015 |
1.1.0 | 35,399 | 2/20/2014 |
1.0.0 | 23,712 | 5/15/2013 |
See the change log for details of this release:
https://github.com/axuno/SmartFormat/blob/master/CHANGES.md