diff --git a/src/SmartFormat.Tests/Extensions/ListFormatterTests.cs b/src/SmartFormat.Tests/Extensions/ListFormatterTests.cs index 39e0a03f..82ae0403 100644 --- a/src/SmartFormat.Tests/Extensions/ListFormatterTests.cs +++ b/src/SmartFormat.Tests/Extensions/ListFormatterTests.cs @@ -113,6 +113,16 @@ public void FormatTest(string format, string expected) } + [Test] + public void NestedFormatSpacers() + { + var smart = Smart.CreateDefaultSmartFormat(); + var names = new[] { "John", "Mary", "Amy" }; + + Assert.AreEqual("John, Mary and Amy", smart.Format("{0:list:{}|{1} | {2} }", names, ",", "and")); + Assert.AreEqual("John, Mary nor Amy", smart.Format("{Names:list:{}|, | {Not:nor|or} }", new { Names = names, Not = true })); + } + [TestCase("{0:list:{}-|}", "A-B-C-D-E-")] [TestCase("{0:list:{}|-}", "A-B-C-D-E")] [TestCase("{0:list:{}|-|+}", "A-B-C-D+E")] diff --git a/src/SmartFormat/Extensions/ListFormatter.cs b/src/SmartFormat/Extensions/ListFormatter.cs index 581903db..9526eea5 100644 --- a/src/SmartFormat/Extensions/ListFormatter.cs +++ b/src/SmartFormat/Extensions/ListFormatter.cs @@ -189,9 +189,9 @@ public bool TryEvaluateFormat(IFormattingInfo formattingInfo) // itemFormat|spacer|lastSpacer // itemFormat|spacer|lastSpacer|twoSpacer var itemFormat = parameters[0]; - var spacer = parameters.Count >= 2 ? parameters[1].GetLiteralText() : string.Empty; - var lastSpacer = parameters.Count >= 3 ? parameters[2].GetLiteralText() : spacer; - var twoSpacer = parameters.Count >= 4 ? parameters[3].GetLiteralText() : lastSpacer; + var spacer = parameters[1]; + var lastSpacer = parameters.Count >= 3 ? parameters[2] : spacer; + var twoSpacer = parameters.Count >= 4 ? parameters[3] : lastSpacer; if (!itemFormat.HasNested) { @@ -230,6 +230,18 @@ public bool TryEvaluateFormat(IFormattingInfo formattingInfo) .Initialize(null, formattingInfo.FormatDetails, format, null); spacerFormattingInfo.Alignment = 0; + // Note: + // Give spacers the data context of the root parent. + // formattingInfo.CurrentValue from the argument to + // TryEvaluateFormat(IFormattingInfo formattingInfo) only contains the list elements. + var rootParent = (formattingInfo as Core.Formatting.FormattingInfo); + do + { + rootParent = rootParent?.Parent; + } while (rootParent?.Parent != null); + + var rootParentValue = rootParent?.CurrentValue; + foreach (var item in items) { CollectionIndex += 1; // Keep track of the index @@ -241,15 +253,15 @@ public bool TryEvaluateFormat(IFormattingInfo formattingInfo) } else if (CollectionIndex < items.Count - 1) { - spacerFormattingInfo.Write(spacer); + WriteSpacer(spacerFormattingInfo, spacer, rootParentValue); } else if (CollectionIndex == 1) { - spacerFormattingInfo.Write(twoSpacer); + WriteSpacer(spacerFormattingInfo, twoSpacer, rootParentValue); } else { - spacerFormattingInfo.Write(lastSpacer); + WriteSpacer(spacerFormattingInfo, lastSpacer, rootParentValue); } // Output the nested format for this item: @@ -268,6 +280,14 @@ public bool TryEvaluateFormat(IFormattingInfo formattingInfo) return true; } + private static void WriteSpacer(IFormattingInfo formattingInfo, Format spacer, object? value) + { + if (spacer.HasNested) + formattingInfo.FormatAsChild(spacer, value); + else + formattingInfo.Write(spacer.GetLiteralText()); + } + /// /// Checks if any of the 's has nullable ? as their first operator. ///