From bcb1da47eb528cbcc6fe476312411ae294eeddc0 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 19 Jul 2026 10:39:49 -0700 Subject: [PATCH] fix(opl): only apply the ':#' cliloc marker to integer values The IPropertyList interpolation handler treated any {value:#} as a cliloc marker (emit '#'). But cliloc numbers are integers; a float/double/decimal with '#' is the standard custom-numeric (digit-placeholder) format, not a cliloc reference. Gate the marker on an integer value type so float/double/decimal {x:#} formats normally, narrowing the ambiguity to the harmless {0:#} integer case ('#0'). Adds ObjectPropertyListSpanAddTests.HashFormat_OnlyMarksIntegers: int {value:#} emits '#'; double {value:#} uses the standard '#' format (no leading '#'). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../ObjectPropertyListSpanAddTests.cs | 15 +++++++++++++++ .../Server/PropertyList/ObjectPropertyList.cs | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Projects/Server.Tests/Tests/PropertyList/ObjectPropertyListSpanAddTests.cs b/Projects/Server.Tests/Tests/PropertyList/ObjectPropertyListSpanAddTests.cs index 408c53386..97e2d9f58 100644 --- a/Projects/Server.Tests/Tests/PropertyList/ObjectPropertyListSpanAddTests.cs +++ b/Projects/Server.Tests/Tests/PropertyList/ObjectPropertyListSpanAddTests.cs @@ -62,6 +62,21 @@ public class ObjectPropertyListSpanAddTests Assert.Equal((1070722, "Custom"), entries[0]); } + [Fact] + public void HashFormat_OnlyMarksIntegers() + { + // Integer {value:#} emits the cliloc marker "#". + var intList = new ObjectPropertyList(null); + intList.Add(1062028, $"{1043009:#}"); + Assert.Equal((1062028, "#1043009"), Decode(intList)[0]); + + // Float {value:#} is the standard '#' custom-numeric (digit-placeholder) format, not a cliloc + // marker -- so no leading '#'. + var dblList = new ObjectPropertyList(null); + dblList.Add(1062028, $"{42.0:#}"); + Assert.Equal((1062028, 42.0.ToString("#")), Decode(dblList)[0]); // "42" + } + [Fact] public void Add_TruncatesArgumentOverMaxLength() { diff --git a/Projects/Server/PropertyList/ObjectPropertyList.cs b/Projects/Server/PropertyList/ObjectPropertyList.cs index 73288f5e1..6404eccbd 100644 --- a/Projects/Server/PropertyList/ObjectPropertyList.cs +++ b/Projects/Server/PropertyList/ObjectPropertyList.cs @@ -384,9 +384,9 @@ public sealed class ObjectPropertyList : IPropertyList, IDisposable public void AppendFormatted(T value, string? format) { - // We support localization '#' cliloc formatter for custom property lists - // This allows someone to build an IPropertyList that creates HTML using the same syntax as LocalizationInterpolationHandler - if (format == "#") + // '#' marks an integer argument as a cliloc ("#"). Integers only -- a float/double/decimal + // '#' is the standard numeric format, not a cliloc marker. + if (format == "#" && value is int or uint or long or ulong or short or ushort or byte or sbyte) { AppendLiteral("#"); format = null;