diff --git a/.docfx/Dockerfile.docfx b/.docfx/Dockerfile.docfx index 9d42262..465ff57 100644 --- a/.docfx/Dockerfile.docfx +++ b/.docfx/Dockerfile.docfx @@ -1,4 +1,4 @@ -ARG NGINX_VERSION=1.31.0-alpine +ARG NGINX_VERSION=1.31.2-alpine FROM --platform=$BUILDPLATFORM nginx:${NGINX_VERSION} AS base RUN rm -rf /usr/share/nginx/html/* diff --git a/.docfx/api/namespaces/Codebelt.Unitify.md b/.docfx/api/namespaces/Codebelt.Unitify.md index c2fb5ca..25e7706 100644 --- a/.docfx/api/namespaces/Codebelt.Unitify.md +++ b/.docfx/api/namespaces/Codebelt.Unitify.md @@ -2,14 +2,46 @@ uid: Codebelt.Unitify summary: *content --- -The `Codebelt.Unitify` namespace offers types that simplify unit management with comprehensive metric and binary support for prefixes, multiples, and submultiples. + +Simplify unit measurement and conversion with **Codebelt.Unitify**, a comprehensive .NET library for managing units with SI unit support, metric prefixes (kilo, mega, milli, micro, etc.), and binary prefixes (kibi, mebi, gibi, etc.). + +To get started, use [`UnitFactory`](xref:Codebelt.Unitify.UnitFactory) to create SI units, or access predefined SI base units via the [`Unit`](xref:Codebelt.Unitify.Unit) class. + +## Start Here + +Begin with **`UnitFactory`** — the primary API for creating SI units with custom precision and base values. Call static methods like `UnitFactory.CreateMeter()` or `UnitFactory.CreateWatt()` to construct units programmatically. + +If you only need standard predefined base units, use the **`Unit`** class directly instead (e.g., `Unit.Meter`, `Unit.Kilogram`) to avoid factory overhead. + +## When to Use + +Use Codebelt.Unitify when you need to: + +- Work with SI base units (meter, kilogram, second, ampere, kelvin, mole, candela) and derived units +- Apply metric (decimal) or binary prefixes to create unit variations (e.g., kilometer, megabyte, gibibyte) +- Convert between different prefix scales while preserving semantic meaning +- Format units using metric, data-centric, or custom naming conventions + +## Getting Started + +**Start here:** Call `UnitFactory.CreateMeter()`, `UnitFactory.CreateWatt()`, or other static factory methods to construct SI units with your desired precision and base values. `UnitFactory` is the primary entry point for programmatic unit creation. + +**Alternative:** If you need one of the standard predefined SI base units (meter, kilogram, second, ampere, kelvin, mole, candela), access them directly via static properties on the `Unit` class (e.g., `Unit.Meter`, `Unit.Kilogram`) to avoid factory overhead. + +Once you have a unit, you can apply metric or binary prefixes in three ways: + +- **Single prefix**: Use `PrefixUnit` to combine a specific prefix with a unit (e.g., create a kilometer from `Unit.Meter` and `DecimalPrefix.Kilo`). +- **Full metric scale table**: Create a `MetricPrefixTable` to explore all available decimal-prefix representations (kilo, mega, giga, etc.) at once. +- **Full binary scale table**: Create a `DataPrefixTable` to explore all available binary-prefix representations (kibi, mebi, gibi, etc.) at once for data/storage contexts. + +Choose `MetricPrefixTable` for general scientific and engineering units; choose `DataPrefixTable` exclusively for data storage and network bandwidth to avoid mixing decimal (1 kB = 1000 bytes) and binary (1 KiB = 1024 bytes) scales. [!INCLUDE [availability-modern](../../includes/availability-modern.md)] -### Extension Methods +## Extension Members |Type|Ext|Methods| |--:|:-:|---| |Prefix|⬇️|`ToPrefixUnit`, `ToBaseUnit`| -|PrefixTable|⬇️|`QuectoOrDefault`, `RontoOrDefault`, `YoctoOrDefault`, `ZeptoOrDefault`, `AttoOrDefault`, `FemtoOrDefault`, `PicoOrDefault`, `NanoOrDefault`, `MicroOrDefault`, `MilliOrDefault`, `CentiOrDefault`, `DeciOrDefault`, `DecaOrDefault`, `HectoOrDefault`, `KiloOrDefault`, `MegaOrDefault`, `GigaOrDefault`, `TeraOrDefault`, `PetaOrDefault`, `ExaOrDefault`, `ZettaOrDefault`, `YottaOrDefault`, `RonnaOrDefault`, `QuettaOrDefault`, `KibiOrDefault`, `MebiOrDefault`, `GibiOrDefault`, `TebiOrDefault`, `PebiOrDefault`, `ExbiOrDefault`, `ZebiOrDefault`, `YobiOrDefault`| +|PrefixTable|⬇️|`QuectoOrDefault`, `RontoOrDefault`, `YoctoOrDefault`, `ZeptoOrDefault`, `AttoOrDefault`, `FemtoOrDefault`, `PicoOrDefault`, `NanoOrDefault`, `MicroOrDefault`, `MilliOrDefault`, `CentiOrDefault`, `DeciOrDefault`, `DecaOrDefault`, `HectoOrDefault`, `KiloOrDefault`, `MegaOrDefault`, `GigaOrDefault`, `TeraOrDefault`, `PetaOrDefault`, `ExaOrDefault`, `ZettaOrDefault`, `YottaOrDefault`, `RonnaOrDefault`, `QuettaOrDefault`, `QuebiOrDefault`, `RobiOrDefault`, `KibiOrDefault`, `MebiOrDefault`, `GibiOrDefault`, `TebiOrDefault`, `PebiOrDefault`, `ExbiOrDefault`, `ZebiOrDefault`, `YobiOrDefault`| |PrefixUnit|⬇️|`ToPrefixValue`, `ToBaseValue`, `ToBaseUnit`, `ToPrefixString`, `ToMetricPrefixTable`, `ToDataPrefixTable`| diff --git a/.docfx/api/types/Codebelt.Unitify.BaseUnit.md b/.docfx/api/types/Codebelt.Unitify.BaseUnit.md new file mode 100644 index 0000000..f414c59 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.BaseUnit.md @@ -0,0 +1,34 @@ +--- +uid: Codebelt.Unitify.BaseUnit +--- + +## Examples + +Represent a unit of measurement with its category, name, and symbol. This example creates several `BaseUnit` instances, demonstrates property access, and shows how to compare units for equality to verify that units with identical properties are considered equal: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class BaseUnitExample +{ + public static void Main() + { + // Create a meter base unit + var meter = new BaseUnit("Length", "Meter", "m"); + + Console.WriteLine($"Category: {meter.Category}"); + Console.WriteLine($"Name: {meter.Name}"); + Console.WriteLine($"Symbol: {meter.Symbol}"); + + // Create a kilogram base unit + var kilogram = new BaseUnit("Mass", "Kilogram", "kg"); + + // Compare base units + var sameUnit = new BaseUnit("Length", "Meter", "m"); + Console.WriteLine($"meter == sameUnit: {meter == sameUnit}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.BinaryPrefix.md b/.docfx/api/types/Codebelt.Unitify.BinaryPrefix.md new file mode 100644 index 0000000..a038687 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.BinaryPrefix.md @@ -0,0 +1,34 @@ +--- +uid: Codebelt.Unitify.BinaryPrefix +--- + +## Examples + +Work with binary prefixes (kibi, mebi, gibi, etc.) for data storage measurements. This example retrieves binary prefix constants, demonstrates property access to find their symbols and multiplier values, converts raw byte values to binary scales using `ToPrefixValue()`, and shows how to construct `PrefixUnit` objects that combine a unit with a binary prefix: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class BinaryPrefixExample +{ + public static void Main() + { + // Get the kibi prefix (2^10) + var kibi = BinaryPrefix.Kibi; + Console.WriteLine($"Kibi symbol: {kibi.Symbol}"); + Console.WriteLine($"Kibi multiplier: {kibi.Multiplier}"); + + // Work with data prefix values + var bytes = 1024.0; + var kibibytes = kibi.ToPrefixValue(bytes); // Convert to kibi scale + Console.WriteLine($"{bytes} bytes = {kibibytes} KiB"); + + // Create a base unit value with binary prefix + var dataUnit = new PrefixUnit(Unit.Byte, 1048576, BinaryPrefix.Mebi); // 1 MiB + Console.WriteLine($"Data unit: {dataUnit}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.DataPrefixTable.md b/.docfx/api/types/Codebelt.Unitify.DataPrefixTable.md new file mode 100644 index 0000000..5370d89 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.DataPrefixTable.md @@ -0,0 +1,34 @@ +--- +uid: Codebelt.Unitify.DataPrefixTable +--- + +## Examples + +Browse all binary prefix representations of a data storage unit. This example creates a `DataPrefixTable` from a byte quantity, then displays both the full table of all binary-scaled representations and an aggregate summary showing which scales are available for that unit value: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class DataPrefixTableExample +{ + public static void Main() + { + // Create a unit representing 1,048,576 bytes (1 MiB) + var byteUnit = UnitFactory.CreateByte(1048576); + + // Create a data prefix table to see all binary scales + var table = new DataPrefixTable(byteUnit); + + // Display all representations + Console.WriteLine("Data storage representations:"); + Console.WriteLine(table.ToString()); + + // Show aggregate summary + Console.WriteLine("\nAggregate:"); + Console.WriteLine(table.ToAggregateString()); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.DecimalPrefix.md b/.docfx/api/types/Codebelt.Unitify.DecimalPrefix.md new file mode 100644 index 0000000..d3abc34 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.DecimalPrefix.md @@ -0,0 +1,40 @@ +--- +uid: Codebelt.Unitify.DecimalPrefix +--- + +## Examples + +Use decimal (metric) prefixes (kilo, mega, milli, micro, etc.) for SI measurements. This example retrieves prefix constants, extracts their symbols and multiplier values, converts raw measurements to prefixed scales using `ToPrefixValue()`, and shows how to construct `PrefixUnit` objects that apply different scales to physical quantities: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class DecimalPrefixExample +{ + public static void Main() + { + // Get the kilo prefix (10^3) + var kilo = DecimalPrefix.Kilo; + Console.WriteLine($"Kilo symbol: {kilo.Symbol}"); + Console.WriteLine($"Kilo multiplier: {kilo.Multiplier}"); + + // Convert a value to kilo scale + var meters = 5000.0; + var kilometers = kilo.ToPrefixValue(meters); + Console.WriteLine($"{meters} m = {kilometers} km"); + + // Create a watt unit with kilo prefix + var kilowatt = new PrefixUnit(Unit.Watt, 5, DecimalPrefix.Kilo); + Console.WriteLine($"Power: {kilowatt}"); + + // Work with micro prefix for small values + var micro = DecimalPrefix.Micro; + var amperes = 0.000005; + var microamperes = micro.ToPrefixValue(amperes); + Console.WriteLine($"{amperes} A = {microamperes} µA"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.MetricPrefixTable.md b/.docfx/api/types/Codebelt.Unitify.MetricPrefixTable.md new file mode 100644 index 0000000..c7fa20f --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.MetricPrefixTable.md @@ -0,0 +1,34 @@ +--- +uid: Codebelt.Unitify.MetricPrefixTable +--- + +## Examples + +Browse all decimal prefix representations of a SI unit. This example creates a `MetricPrefixTable` from a watt quantity, then displays both the full table showing all decimal-scaled (power-of-10) representations and an aggregate summary indicating which SI prefix scales are available for that unit value: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class MetricPrefixTableExample +{ + public static void Main() + { + // Create a unit: 11,745 watts (approximately 11.745 kW) + var wattUnit = UnitFactory.CreateWatt(11745); + + // Create a metric prefix table to see all decimal scales + var table = new MetricPrefixTable(wattUnit); + + // Display all representations from quecto to yotta + Console.WriteLine("Metric prefix representations:"); + Console.WriteLine(table.ToString()); + + // Show aggregate summary + Console.WriteLine("\nAggregate:"); + Console.WriteLine(table.ToAggregateString()); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.NamingStyle.md b/.docfx/api/types/Codebelt.Unitify.NamingStyle.md new file mode 100644 index 0000000..88134f9 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.NamingStyle.md @@ -0,0 +1,31 @@ +--- +uid: Codebelt.Unitify.NamingStyle +--- + +## Examples + +Control how units are formatted as text by choosing between symbol-based and compound naming styles. This example creates a prefix unit, displays its default representation, then creates another using a setup action to apply `NamingStyle.Compound` so the output shows full names instead of abbreviations: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class NamingStyleExample +{ + public static void Main() + { + // Create a kilometer with Default naming + var kilometer = new PrefixUnit(Unit.Meter, 1.0, DecimalPrefix.Kilo); + Console.WriteLine($"Default: {kilometer}"); + + // Use Compound naming style to show compound names + var compoundKilometer = new PrefixUnit(Unit.Meter, 5.0, DecimalPrefix.Kilo, o => + { + o.Style = NamingStyle.Compound; + }); + Console.WriteLine($"Compound: {compoundKilometer}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.PrefixExtensions.md b/.docfx/api/types/Codebelt.Unitify.PrefixExtensions.md new file mode 100644 index 0000000..490fcfd --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.PrefixExtensions.md @@ -0,0 +1,54 @@ +--- +uid: Codebelt.Unitify.PrefixExtensions +--- + +## Examples + +Use extension methods on prefix types to extract base unit information and convert values. This example demonstrates a realistic workflow where you start with decimal and binary prefix instances (prerequisites: `DecimalPrefix.Kilo` and `BinaryPrefix.Kibi`), then use the `ToPrefixUnit()` extension method to combine a prefix with a unit type to create scaled units (setup), and finally invoke `ToBaseUnit()` and `ToPrefixValue()` methods to demonstrate conversion and scaling operations. The outcome shows how extension methods simplify the creation of prefix-unit combinations and value scaling without requiring manual unit construction: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class PrefixExtensionsExample +{ + public static void Main() + { + // Create instances of DecimalPrefix and BinaryPrefix + var kilo = DecimalPrefix.Kilo; + var kibi = BinaryPrefix.Kibi; + + // Use the ToPrefixUnit extension method to create scaled units + // Create a kilo-meter by combining the Kilo prefix with a meter unit + var meterUnit = new UnitTestWrapper(); // Implement IUnit + var kilometer = kilo.ToPrefixUnit(meterUnit); + Console.WriteLine($"Kilometer: {kilometer}"); + + // Create a kibi-byte using the Kibi prefix + var byteUnit = new UnitTestWrapper(); // Implement IUnit + var kibibyte = kibi.ToPrefixUnit(byteUnit); + Console.WriteLine($"Kibibyte: {kibibyte}"); + + // Use ToBaseUnit extension method to create a unit with prefix applied to a base unit + var wattUnit = kilo.ToBaseUnit(Unit.Watt, 5.0); + Console.WriteLine($"Kilowatt (5 kW): {wattUnit}"); + + // Use ToPrefixValue to convert a raw value to prefix scale + var rawValue = 5000.0; + var prefixedValue = kilo.ToPrefixValue(rawValue); + Console.WriteLine($"{rawValue} base units = {prefixedValue} kilo units"); + } +} + +// Simple test implementation of IUnit +public class UnitTestWrapper : IUnit +{ + public string Category => "Data"; + public string Name => "byte"; + public string Symbol => "B"; + public double Value => 1.0; + public UnitFormatOptions FormatOptions => new(); +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.PrefixStyle.md b/.docfx/api/types/Codebelt.Unitify.PrefixStyle.md new file mode 100644 index 0000000..7dd22ab --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.PrefixStyle.md @@ -0,0 +1,31 @@ +--- +uid: Codebelt.Unitify.PrefixStyle +--- + +## Examples + +Control how data prefix tables format output using binary (powers of 1024) or decimal (powers of 10) scales. This example demonstrates the `ToString(PrefixStyle)` method on `DataPrefixTable` to display the same byte quantity in two different prefix styles, allowing you to see how the same value appears with binary vs. decimal formatting: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class PrefixStyleExample +{ + public static void Main() + { + // Create a data unit table + var byteUnit = UnitFactory.CreateByte(1048576); // 1,048,576 bytes + var dataTable = new DataPrefixTable(byteUnit); + + // Display with binary style formatting (1024-based prefixes) + Console.WriteLine("Binary prefix style (powers of 1024):"); + Console.WriteLine(dataTable.ToString(PrefixStyle.Binary)); + + Console.WriteLine("\nDecimal prefix style (powers of 10):"); + Console.WriteLine(dataTable.ToString(PrefixStyle.Decimal)); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.PrefixTableExtensions.md b/.docfx/api/types/Codebelt.Unitify.PrefixTableExtensions.md new file mode 100644 index 0000000..0981cd4 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.PrefixTableExtensions.md @@ -0,0 +1,158 @@ +--- +uid: Codebelt.Unitify.PrefixTableExtensions +--- + +## Examples + +Lookup specific SI and binary prefix scales from a table to obtain scaled representations at each available magnitude. The setup prerequisite is a unit value large enough to have multiple valid prefix scales (for example, 1E21 watts or 1 TiB of bytes). This example creates `MetricPrefixTable` and `DataPrefixTable` instances (setup phase), then demonstrates the lookup workflow by calling available `*OrDefault()` extension methods to check which prefix scales exist at each magnitude level. The outcome displays all available prefix representations organized by scale category (SI decimal large/small scales, binary data scales, and miscellaneous decimal scales), allowing you to see the complete prefix transformation options. In production code, you would typically call only the specific `*OrDefault()` methods relevant to your domain (for example, `KiloOrDefault()` and `MebiOrDefault()`) to avoid unnecessary allocations and focus on the prefix scales needed for your use case. + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class PrefixTableExtensionsExample +{ + public static void Main() + { + // Create a metric prefix table from a large watt value + var wattUnit = UnitFactory.CreateWatt(1E21); // Very large value in watts + var table = new MetricPrefixTable(wattUnit); + + // QuettaOrDefault: Scale the unit to the quetta (10^30) prefix, returning null if the value + // does not have a valid quetta representation. Use this for extremely large scientific values. + Console.WriteLine("=== SI Decimal Prefixes (Large Scales) ==="); + var quetta = table.QuettaOrDefault(); + if (quetta != null) Console.WriteLine($"Quetta: {quetta}"); + + // ZettaOrDefault: Scale the unit to the zetta (10^21) prefix, returning null if unavailable. + // Common for very large data or energy quantities in scientific computing. + var zetta = table.ZettaOrDefault(); + if (zetta != null) Console.WriteLine($"Zetta: {zetta}"); + + // YottaOrDefault: Scale the unit to the yotta (10^24) prefix, returning null if not applicable. + // Used for astronomical or theoretical quantities exceeding exabytes or exawatts. + var yotta = table.YottaOrDefault(); + if (yotta != null) Console.WriteLine($"Yotta: {yotta}"); + + // Common SI decimal prefixes: Scale from very large (mega, giga) to medium scales. + // KiloOrDefault, MegaOrDefault, GigaOrDefault, TeraOrDefault, and PetaOrDefault cover + // the most frequently used commercial and engineering scales. + var kilo = table.KiloOrDefault(); + if (kilo != null) Console.WriteLine($"Kilo: {kilo}"); + + var mega = table.MegaOrDefault(); + if (mega != null) Console.WriteLine($"Mega: {mega}"); + + var giga = table.GigaOrDefault(); + if (giga != null) Console.WriteLine($"Giga: {giga}"); + + var tera = table.TeraOrDefault(); + if (tera != null) Console.WriteLine($"Tera: {tera}"); + + var peta = table.PetaOrDefault(); + if (peta != null) Console.WriteLine($"Peta: {peta}"); + + var exa = table.ExaOrDefault(); + if (exa != null) Console.WriteLine($"Exa: {exa}"); + + // Small SI decimal prefixes: Scale from milli (10^-3) down to quecto (10^-30). + // These are essential for medical, laboratory, and precision manufacturing applications. + // MilliOrDefault and MicroOrDefault are the most common for everyday engineering. + Console.WriteLine("\n=== SI Decimal Prefixes (Small Scales) ==="); + var milli = table.MilliOrDefault(); + if (milli != null) Console.WriteLine($"Milli: {milli}"); + + var micro = table.MicroOrDefault(); + if (micro != null) Console.WriteLine($"Micro: {micro}"); + + var nano = table.NanoOrDefault(); + if (nano != null) Console.WriteLine($"Nano: {nano}"); + + var pico = table.PicoOrDefault(); + if (pico != null) Console.WriteLine($"Pico: {pico}"); + + var femto = table.FemtoOrDefault(); + if (femto != null) Console.WriteLine($"Femto: {femto}"); + + var atto = table.AttoOrDefault(); + if (atto != null) Console.WriteLine($"Atto: {atto}"); + + var zepto = table.ZeptoOrDefault(); + if (zepto != null) Console.WriteLine($"Zepto: {zepto}"); + + var yocto = table.YoctoOrDefault(); + if (yocto != null) Console.WriteLine($"Yocto: {yocto}"); + + var ronto = table.RontoOrDefault(); + if (ronto != null) Console.WriteLine($"Ronto: {ronto}"); + + var quecto = table.QuectoOrDefault(); + if (quecto != null) Console.WriteLine($"Quecto: {quecto}"); + + // Binary prefix scales in a data table: Scale from kibi (2^10) through yobi (2^80). + // QuebiOrDefault and RobiOrDefault represent the newest binary scales (added in 2022). + // Use binary prefixes exclusively for data storage and network bandwidth to avoid + // confusion with decimal SI scales; 1 KiB = 1024 bytes, while 1 kB = 1000 bytes. + Console.WriteLine("\n=== Binary Prefixes (Data Table) ==="); + var byteUnit = UnitFactory.CreateByte(1099511627776); // 1 TiB + var dataTable = new DataPrefixTable(byteUnit); + + // QuebiOrDefault: Scale to the quebi (2^100) prefix for data storage. + // Used in theoretical or future-scale data center planning. + var quobi = dataTable.QuebiOrDefault(); + if (quobi != null) Console.WriteLine($"Quebi: {quobi}"); + + // RobiOrDefault: Scale to the robi (2^90) prefix, the second-newest binary scale. + var robi = dataTable.RobiOrDefault(); + if (robi != null) Console.WriteLine($"Robi: {robi}"); + + // Common binary prefixes: KibiOrDefault (1024 bytes), MebiOrDefault (1 million bytes), + // GibiOrDefault (1 billion bytes), and TebiOrDefault (1 trillion bytes) are the most + // commonly encountered in modern storage and memory specifications. + var kibi = dataTable.KibiOrDefault(); + if (kibi != null) Console.WriteLine($"Kibi: {kibi}"); + + var mebi = dataTable.MebiOrDefault(); + if (mebi != null) Console.WriteLine($"Mebi: {mebi}"); + + var gibi = dataTable.GibiOrDefault(); + if (gibi != null) Console.WriteLine($"Gibi: {gibi}"); + + var tebi = dataTable.TebiOrDefault(); + if (tebi != null) Console.WriteLine($"Tebi: {tebi}"); + + var pebi = dataTable.PebiOrDefault(); + if (pebi != null) Console.WriteLine($"Pebi: {pebi}"); + + var exbi = dataTable.ExbiOrDefault(); + if (exbi != null) Console.WriteLine($"Exbi: {exbi}"); + + var zebi = dataTable.ZebiOrDefault(); + if (zebi != null) Console.WriteLine($"Zebi: {zebi}"); + + var yobi = dataTable.YobiOrDefault(); + if (yobi != null) Console.WriteLine($"Yobi: {yobi}"); + + // Additional decimal prefixes: CentiOrDefault, DeciOrDefault, DecaOrDefault, and HectoOrDefault + // cover non-standard but occasionally used scales in specialized fields like chemistry + // and older engineering references. RonnaOrDefault and RontoOrDefault are the newest decimal scales. + Console.WriteLine("\n=== Additional Decimal Prefixes ==="); + var centi = table.CentiOrDefault(); + if (centi != null) Console.WriteLine($"Centi: {centi}"); + + var deci = table.DeciOrDefault(); + if (deci != null) Console.WriteLine($"Deci: {deci}"); + + var deca = table.DecaOrDefault(); + if (deca != null) Console.WriteLine($"Deca: {deca}"); + + var hecto = table.HectoOrDefault(); + if (hecto != null) Console.WriteLine($"Hecto: {hecto}"); + + var ronna = table.RonnaOrDefault(); + if (ronna != null) Console.WriteLine($"Ronna: {ronna}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.PrefixUnit.md b/.docfx/api/types/Codebelt.Unitify.PrefixUnit.md new file mode 100644 index 0000000..2c2a95d --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.PrefixUnit.md @@ -0,0 +1,37 @@ +--- +uid: Codebelt.Unitify.PrefixUnit +--- + +## Examples + +Represent a unit of measurement with an associated prefix. This example demonstrates creating `PrefixUnit` instances with different combinations of base units and prefixes, shows how to construct one from an existing unit, and demonstrates that the prefix parameter is optional (a unit with no prefix has the default `None` prefix): + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class PrefixUnitExample +{ + public static void Main() + { + // Create a kilometer (meter with kilo prefix) + var kilometer = new PrefixUnit(Unit.Meter, 1.0, DecimalPrefix.Kilo); + Console.WriteLine($"Distance: {kilometer}"); + + // Create from an existing unit + var wattUnit = UnitFactory.CreateWatt(500); + var kilowatt = new PrefixUnit(wattUnit, DecimalPrefix.Kilo); + Console.WriteLine($"Power: {kilowatt}"); + + // Create a megahertz + var megahertz = new PrefixUnit(Unit.Hertz, 100.0, DecimalPrefix.Mega); + Console.WriteLine($"Frequency: {megahertz}"); + + // Prefix can be None (no prefix applied) + var baseWatt = new PrefixUnit(Unit.Watt, 2500.0); + Console.WriteLine($"No prefix: {baseWatt}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.PrefixUnitExtensions.md b/.docfx/api/types/Codebelt.Unitify.PrefixUnitExtensions.md new file mode 100644 index 0000000..d2489d8 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.PrefixUnitExtensions.md @@ -0,0 +1,52 @@ +--- +uid: Codebelt.Unitify.PrefixUnitExtensions +--- + +## Examples + +Convert and transform prefix units to other prefix scales and formats. This example demonstrates extension methods like `ToBaseUnit()`, `ToBaseValue()`, `ToPrefixValue()`, `ToMetricPrefixTable()`, `ToDataPrefixTable()`, and `ToPrefixString()`, showing how to extract different representations and scale conversions from a prefix unit: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class PrefixUnitExtensionsExample +{ + public static void Main() + { + // Create a kilowatt + var kilowatt = new PrefixUnit(Unit.Watt, 5.0, DecimalPrefix.Kilo); + Console.WriteLine($"Original: {kilowatt}"); + + // Convert to base unit using extension method + var wattUnit = kilowatt.ToBaseUnit(); + Console.WriteLine($"Base unit: {wattUnit}"); + + // Get the base value in watts + var baseValue = kilowatt.ToBaseValue(); + Console.WriteLine($"Base value: {baseValue} W"); + + // Get the prefix value (the numeric part with the prefix applied) + var prefixValue = kilowatt.ToPrefixValue(); + Console.WriteLine($"Prefix value: {prefixValue}"); + + // Convert to a metric prefix table and look up different scales + var metricTable = kilowatt.ToMetricPrefixTable(); + var megawatt = metricTable?.MegaOrDefault(); + if (megawatt != null) + { + Console.WriteLine($"Mega scale: {megawatt}"); + } + + // Convert to a data prefix table for binary scales + var dataTable = kilowatt.ToDataPrefixTable(); + Console.WriteLine($"Data table available: {dataTable != null}"); + + // Get a formatted prefix string + var prefixString = kilowatt.ToPrefixString(); + Console.WriteLine($"Prefix string: {prefixString}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.PrefixUnitFormatter.md b/.docfx/api/types/Codebelt.Unitify.PrefixUnitFormatter.md new file mode 100644 index 0000000..00acf4c --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.PrefixUnitFormatter.md @@ -0,0 +1,42 @@ +--- +uid: Codebelt.Unitify.PrefixUnitFormatter +--- + +## Examples + +Format prefix units with custom numeric and culture-specific representations. This example demonstrates creating a prefix unit with custom format options, shows the default string representation, uses a `PrefixUnitFormatter` instance for custom formatting with a `CultureInfo`, and displays how to create a metric prefix table from a prefix unit to show multiple scaled representations: + +```csharp +using System; +using System.Globalization; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class PrefixUnitFormatterExample +{ + public static void Main() + { + // Create a formatted prefix unit + var kilowatt = new PrefixUnit(Unit.Watt, 5.5, DecimalPrefix.Kilo, options => + { + options.NumberFormat = "F2"; // 2 decimal places + }); + + // Default formatting + Console.WriteLine($"Default: {kilowatt}"); + + // Create a formatter instance + var formatter = new PrefixUnitFormatter(); + + // Format with custom format string + var formatted = formatter.Format("{0:F1} {1}", kilowatt, CultureInfo.CurrentCulture); + Console.WriteLine($"Formatted: {formatted}"); + + // Format with metric prefix table for detailed output + var table = new MetricPrefixTable(kilowatt); + Console.WriteLine("Prefix table:"); + Console.WriteLine(table.ToString()); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.UnitFactory.md b/.docfx/api/types/Codebelt.Unitify.UnitFactory.md new file mode 100644 index 0000000..2dd027e --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.UnitFactory.md @@ -0,0 +1,36 @@ +--- +uid: Codebelt.Unitify.UnitFactory +--- + +## Examples + +Create SI units with predefined base values using factory methods. This example demonstrates factory methods for different unit types (meter, watt, byte, and second), each creating a fully-configured unit instance with a base value so you can immediately start formatting and working with the result: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class UnitFactoryExample +{ + public static void Main() + { + // Create a meter unit + var meter = UnitFactory.CreateMeter(100); + Console.WriteLine($"Distance: {meter}"); + + // Create a watt unit + var watt = UnitFactory.CreateWatt(1500); + Console.WriteLine($"Power: {watt}"); + + // Create a byte unit for data storage + var byte_unit = UnitFactory.CreateByte(1024); + Console.WriteLine($"Data: {byte_unit}"); + + // Create a second unit for time + var second = UnitFactory.CreateSecond(3600); + Console.WriteLine($"Time: {second}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.UnitFormatOptions.md b/.docfx/api/types/Codebelt.Unitify.UnitFormatOptions.md new file mode 100644 index 0000000..bd5bbd7 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.UnitFormatOptions.md @@ -0,0 +1,56 @@ +--- +uid: Codebelt.Unitify.UnitFormatOptions +--- + +## Examples + +Configure how units are formatted when converted to strings by creating and using `UnitFormatOptions` instances. This example demonstrates creating `UnitFormatOptions` directly with custom settings, applying those settings to units via factory methods, and shows how different number formats and naming styles produce different string representations: + +```csharp +using System; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class UnitFormatOptionsExample +{ + public static void Main() + { + // Create a UnitFormatOptions instance directly + var options = new UnitFormatOptions + { + NumberFormat = "F2", + Style = NamingStyle.Compound + }; + + // Apply the options to a unit via UnitFactory + var watt = UnitFactory.CreateWatt(1234.567, setup: opts => + { + opts.NumberFormat = options.NumberFormat; + opts.Style = options.Style; + }); + + Console.WriteLine($"With custom options: {watt}"); + + // Create another UnitFormatOptions with different settings + var symbolOptions = new UnitFormatOptions + { + NumberFormat = "#,##0.##", + Style = NamingStyle.Symbol + }; + + // Display the configured options + Console.WriteLine($"Number Format: {symbolOptions.NumberFormat}"); + Console.WriteLine($"Style: {symbolOptions.Style}"); + + // Apply symbol options to a meter unit + var meter = UnitFactory.CreateMeter(1500.0, setup: opts => + { + opts.NumberFormat = symbolOptions.NumberFormat; + opts.Style = symbolOptions.Style; + }); + + Console.WriteLine($"Meter with symbol options: {meter}"); + } +} +``` diff --git a/.docfx/api/types/Codebelt.Unitify.UnitFormatter.md b/.docfx/api/types/Codebelt.Unitify.UnitFormatter.md new file mode 100644 index 0000000..6f57603 --- /dev/null +++ b/.docfx/api/types/Codebelt.Unitify.UnitFormatter.md @@ -0,0 +1,43 @@ +--- +uid: Codebelt.Unitify.UnitFormatter +--- + +## Examples + +Format units with custom numeric representations and culture-specific formatting. This example demonstrates creating units with different base values, shows the default string representation, applies custom format options via the factory method, and demonstrates using a `UnitFormatter` instance for explicit formatting with a specific `CultureInfo`: + +```csharp +using System; +using System.Globalization; +using Codebelt.Unitify; + +namespace Unitify.Samples; + +public class UnitFormatterExample +{ + public static void Main() + { + // Create units with different values + var watt = UnitFactory.CreateWatt(1234.5); + var kilowatt = UnitFactory.CreateWatt(1234.5, DecimalPrefix.Kilo); + + // Display default string representation + Console.WriteLine($"1 Watt: {watt}"); + Console.WriteLine($"1 Kilowatt: {kilowatt}"); + + // Create a unit with custom formatting options + var formattedWatt = UnitFactory.CreateWatt(1234.5, setup: options => + { + options.NumberFormat = "N2"; + options.Style = NamingStyle.Compound; + }); + + Console.WriteLine($"With custom formatting: {formattedWatt}"); + + // Create a formatter instance for custom formatting scenarios + var formatter = new UnitFormatter(); + string customFormat = formatter.Format("Power: {0:F1}", watt, CultureInfo.InvariantCulture); + Console.WriteLine(customFormat); + } +} +``` diff --git a/.docfx/docfx.json b/.docfx/docfx.json index 1d48ad3..0979987 100644 --- a/.docfx/docfx.json +++ b/.docfx/docfx.json @@ -25,14 +25,15 @@ { "files": [ "api/**/*.yml", - "api/**/*.md", "packages/**/*.md", "toc.yml", "*.md" ], "exclude": [ "bin/**", - "obj/**" + "obj/**", + "api/namespaces/**", + "api/types/**" ] } ], @@ -67,7 +68,8 @@ "overwrite": [ { "files": [ - "api/namespaces/**.md" + "api/namespaces/**/*.md", + "api/types/**/*.md" ], "exclude": [ "obj/**", diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 50f8226..ebd9234 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -204,7 +204,8 @@ jobs: security-events: write deploy: - if: github.event_name != 'pull_request' + # Avoid skipped optional jobs (for example disabled macOS matrix runs) from suppressing deployment. + if: ${{ always() && github.event_name != 'pull_request' && needs.build.result == 'success' && needs.pack.result == 'success' && needs.test_qualitygate.result == 'success' && needs.sonarcloud.result == 'success' && needs.codecov.result == 'success' && needs.codeql.result == 'success' }} name: call-nuget needs: [build, pack, test_qualitygate, sonarcloud, codecov, codeql] uses: codebeltnet/jobs-nuget-push/.github/workflows/default.yml@v3 diff --git a/.nuget/Codebelt.Unitify/PackageReleaseNotes.txt b/.nuget/Codebelt.Unitify/PackageReleaseNotes.txt index 38cf15c..ceed5a4 100644 --- a/.nuget/Codebelt.Unitify/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Unitify/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.0.9 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.0.8 Availability: .NET 10 and .NET 9 diff --git a/AGENTS.md b/AGENTS.md index 098500f..c821baf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -56,8 +56,62 @@ Agents must never automatically commit code changes or push to remote repositori **Rationale:** Automatic commits can clutter history with incomplete work, temporary debugging code, or unintended changes. Unexpected remote operations risk overwriting or losing commits on shared branches. Always require explicit user approval before performing these actions. -## Official Documentation + +## DocFX Documentation Maintenance -- Public API conventions belong in `.docfx/api/namespaces/` and should be treated as the official documentation source for library behavior and naming vocabulary. -- When adding or renaming public APIs, update the relevant namespace page in `.docfx/api/namespaces/` if the change introduces or clarifies a convention. -- Keep internal reasoning, exploratory notes, and agent discussion out of DocFX pages; summarize only stable public guidance. +When changing public .NET APIs, keep the DocFX documentation current in the same change set. + +Documentation updates must cover public API only. Do not document private or internal types or members. Do not create namespace overview pages for namespaces that contain no public API. + +Public non-abstraction types — including enums, structs, records, plain classes, and static extension containers — are valid documentation targets. Generic public types and generic extension methods are valid documentation targets too. Do not exclude a type solely because it is generic or because reflection reports it as abstract and sealed (that is the IL pattern for a static class). + +For public non-abstraction types, include at least one realistic, copy/paste-ready usage example on the generated type page/overwrite section for that type UID. For example, a public `Class1` requires an example on the `Class1` API page, not only on the namespace page. Prefer deriving examples from existing unit, functional, or integration tests, but convert test code into real-life consumer-oriented usage. + +Missing type examples must be added through per-type DocFX overwrite files under `.docfx/api/types/{TypeUid}.md` in Codebelt repositories. Namespace overview text and `Extension Members` tables are not substitutes for type-page examples. + +Public extension methods must have examples too. Listing an extension method in an `Extension Members` table is required, but it is not enough. + +All added or changed code samples must be deterministic and verified to compile. Do not add pseudo-code, ellipses, hidden test helpers, or examples that rely on unverified behavior. + +Compilation is necessary but not sufficient. Do not present runtime implementation names such as `services.GetType().Name` or `host.GetType().FullName` as the example outcome. Show application behavior, configured state, a resolved domain service, an HTTP response, or another result that explains why a caller uses the API. Application-entry-point examples must not declare an empty local `Program` type merely to compile; show a real entry point or clearly identify the referenced application project. + +Every namespace containing public API must have a DocFX namespace overview page named after the namespace, such as `X.Y.Z.md`, under `.docfx/api/namespaces/`, using DocFX overwrite front matter with the namespace `uid`. + +Namespace pages must identify key entry points from release notes, package documentation, public factories/builders, and strong functional tests, then help readers choose among adjacent workflows. When the package complements a well-known upstream API, compare concrete acquisition, customization, lifecycle, and sharing tradeoffs from current official guidance; do not claim drop-in replacement compatibility without evidence. + +Namespaces exposing public extension methods must document those extension members at namespace level. The namespace page must include an `Extension Members` table listing the extended type, the extension marker, and the public extension methods. Extension members are rendered under the heading `Extension Members`. + +Both namespace overwrite files and type overwrite files are required deliverables in the same run. Generating only namespace pages or only type pages is incomplete. + +`docfx.json` must keep namespace and type overwrite files in separate subdirectories. `build.overwrite` must include both `api/namespaces/**/*.md` (for namespace pages) and `api/types/**/*.md` (for type pages). `build.content` must exclude both `api/namespaces/**` and `api/types/**` to prevent overwrite Markdown from being treated as conceptual content. Do not use `api/**/*.md` under `build.overwrite` or `build.content`. + +Availability must be documented by referencing the appropriate include file when one exists, or by adding explicit availability text when no suitable include exists. Availability must reflect the actual target frameworks, conditional compilation, and project configuration. + +For conditionally compiled APIs, choose the executable test framework from the asset that contains the API. Inspect the preprocessor condition, project TFMs, package `lib/` assets, and resolved consumer asset before changing a sample. For APIs under `NETSTANDARD2_0` or `NETSTANDARD2_0_OR_GREATER`, when modern `lib/netX.0/` assets also exist, use `net48` (or another supported .NET Framework target from `net462` onward) so the consumer selects `lib/netstandard2.0/`. Never use `netstandard*` as an executable target, and never use a modern `netX.0` target when it selects an asset where the API is absent. For other TFM guards, select a runnable consumer TFM that resolves to the containing asset and confirm that selection from restore or build evidence. + +Preserve manual documentation edits. Prefer additive changes, but correct stale or contradictory information so documentation remains accurate. + +Preserve working Markdown links, `Related:` references, and historical URL citations during prose rewrites. Remove or replace a URL only after directly verifying that the current destination returns HTTP 404. Timeouts, 403s, rate limits, DNS failures, and other lookup problems are not removal evidence. + +Interim scratch artifacts do not belong in the repository working tree. Store assessment queues, project manifests, review reports, captured validator output, progress notes, and one-off helper scripts in temp or session storage instead. New working-tree files are only legitimate when they are the managed `AGENTS.md` block, the active `docfx.json`, the deterministic `skip-compile-allowlist.json` waiver file when one is truly required, or DocFX-authored namespace/type Markdown that maps to a real public namespace or type. Everything else is blocking cleanup work, not a documentation deliverable. The validator auto-detects generic-arity type families (such as `MutableTuple`1`..`MutableTuple`N`) and skips redundant sibling examples from the public API surface alone, so no family-skip manifest is ever written into the repository. + +Skip markers are waivers, not fixes. A skip marker only suppresses compilation when it both existed before the current run and matches an entry in `.docfx/skip-compile-allowlist.json`. Each allowlist entry must include `diagnosticCode`, `filePath`, `uid` or `symbol`, `reason`, `approval`, and `lifetime` (`temporary` or `permanent`). Newly introduced or unallowlisted skip markers remain fail-level diagnostics and do not permit a completion claim. + +Do not emit a final report, audit result, completion summary, or handoff while `summary.canClaimCompletion` is false, `summary.remainingWorkItems` is greater than zero, `summary.remainingGates` is non-empty, `summary.fullVerificationRan` is false, fail-level diagnostics remain, `summary.newlyIntroducedSkipMarkers` is non-zero, or `summary.interimArtifacts` is non-zero. Large queues, many changed files, repetitive next steps, long runtimes, context pressure, session length, task size, or a "stable queue" are not valid stop reasons; the next action must be another remediation batch, a validator rerun, a validator/tooling fix, or a true blocker with exact evidence. + +Context pressure is not a completion condition. If the session feels constrained while work remains, continue with a smaller deterministic batch, regenerate deterministic queue state such as `--assessment-queue`, `--project-manifest`, or the active dry-run manifest/review pair, or report a true tooling failure with the exact command, exit code, and output. When naming a queue-state regeneration command, resolve it to a concrete temp/session path instead of leaving `` as a placeholder. Do not stop with phrases like "given context constraints", "best done in a follow-up", "remaining work requires authoring", "this is a massive task", or "I will provide a focused summary". A context-sized handoff while work remains is `FAIL_CONTEXT_HANDOFF_WITH_REMAINING_WORK`; the remediation is to continue with a smaller deterministic batch. + +Before completing documentation work, run the relevant verification commands, normally: + +```bash +dotnet build +dotnet test +dotnet run --file /scripts/docfx.cs -- --repo-root . --build-api-model --validate-samples --verify-docfx-build +``` + +Codebelt repositories are normally strong-name signed with a `.snk` file in the repository root on the main author's codespace. Preserve and copy that root `.snk` file when building a temporary copy. If the repository or temp copy has no root `.snk`, run build and test verification with `-p:SkipSignAssembly=true`, for example `dotnet build -p:SkipSignAssembly=true` and `dotnet test -p:SkipSignAssembly=true`. + +The final DocFX verification must run outside the working tree when possible. The `--verify-docfx-build` option copies the repository to a temp workspace, runs DocFX against the resolved `docfx.json` there, and removes the temp workspace afterward so generated API YAML, manifest files, and site output do not flood git status. Do not call the work complete until the final JSON reports `summary.fullVerificationRan: true`, `summary.canClaimCompletion: true`, `summary.remainingWorkItems: 0`, an empty `summary.remainingGates`, an empty `summary.remainingDiagnosticsByCode`, `summary.newlyIntroducedSkipMarkers: 0`, and `summary.interimArtifacts: 0`. + +If a command cannot be run, report the exact limitation or failure instead of claiming the documentation was verified. + diff --git a/CHANGELOG.md b/CHANGELOG.md index ef597f7..253d978 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,28 @@ For more details, please refer to `PackageReleaseNotes.txt` on a per assembly ba > [!NOTE] > Changelog entries prior to version 9.0.0 was migrated from previous versions of [Cuemon.Core](https://github.com/gimlichael/Cuemon/commit/83e0c7af2cdaa07351e878fa7276558838f2e7e6). +## [10.0.9] - 2026-06-30 + +This is a patch release focused on comprehensive API documentation, test infrastructure updates, and continuous integration improvements. + +### Added + +- Complete DocFX API documentation for all public types in the Codebelt.Unitify namespace with per-type overwrite files covering examples and usage guidance, +- Namespace overview documentation for Codebelt.Unitify providing Start Here, When to Use, and Getting Started sections with practical guidance on unit creation, prefix application, and metric vs binary prefix table usage, +- Comprehensive DocFX documentation maintenance guidelines in AGENTS.md covering API documentation requirements, namespace and type page guidelines, example validation, link preservation, availability documentation, and final verification procedures for code sample compilation and DocFX build validation. + +### Changed + +- Codebelt.Extensions.Xunit.App upgraded from 11.1.0 to 11.1.1 for enhanced unit test infrastructure support, +- Cuemon.Core upgraded from 10.5.3 to 10.5.4 with latest improvements across all supported target frameworks, +- Documentation infrastructure updated with Dockerfile.docfx nginx image upgraded to 1.31.2 and docfx.json restructured to separate namespace and type API documentation into distinct subdirectories, +- Continuous integration deployment condition refactored to explicitly check all required job results, preventing skipped optional jobs from suppressing deployment, +- Microsoft.NET.Test.SDK upgraded from 18.6.0 to 18.7.0 for improved test runner compatibility and latest test infrastructure improvements. + +### Fixed + +- CI/CD deployment workflow now correctly respects all job results using always() condition check instead of only preventing pull request deployments. + ## [10.0.8] - 2026-06-05 This is a service update that focuses on package dependencies. @@ -150,7 +172,11 @@ This is a service update that primarily focuses on package dependencies and mino - ByteUnit class in the Codebelt.Unitify namespace to have 0 duplicated blocks of lines of code - UnitPrefixFormatter class in the Codebelt.Unitify namespace to be compliant with https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1822 -[Unreleased]: https://github.com/codebeltnet/unitify/compare/v10.0.5...HEAD +[Unreleased]: https://github.com/codebeltnet/unitify/compare/v10.0.9...HEAD +[10.0.9]: https://github.com/codebeltnet/unitify/compare/v10.0.8...v10.0.9 +[10.0.8]: https://github.com/codebeltnet/unitify/compare/v10.0.7...v10.0.8 +[10.0.7]: https://github.com/codebeltnet/unitify/compare/v10.0.6...v10.0.7 +[10.0.6]: https://github.com/codebeltnet/unitify/compare/v10.0.5...v10.0.6 [10.0.5]: https://github.com/codebeltnet/unitify/compare/v10.0.4...v10.0.5 [10.0.4]: https://github.com/codebeltnet/unitify/compare/v10.0.3...v10.0.4 [10.0.3]: https://github.com/codebeltnet/unitify/compare/v10.0.2...v10.0.3 diff --git a/Directory.Packages.props b/Directory.Packages.props index 5877f2a..ac07075 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,9 +3,9 @@ true - - - + + +