diff --git a/Src/xWorks/ConfiguredLcmGenerator.cs b/Src/xWorks/ConfiguredLcmGenerator.cs index 948ed017cb..ddcaacd052 100644 --- a/Src/xWorks/ConfiguredLcmGenerator.cs +++ b/Src/xWorks/ConfiguredLcmGenerator.cs @@ -2776,7 +2776,15 @@ private static IFragment GenerateContentForString(ITsString fieldValue, Configur externalLink = props.GetStrPropValue((int)FwTextPropType.ktptObjData); } writingSystem = settings.Cache.WritingSystemFactory.GetStrFromWs(fieldValue.get_WritingSystem(i)); - GenerateRunWithPossibleLink(settings, writingSystem, writer, style, text, linkTarget, rightToLeft, config, first, externalLink); + + // The purpose of the boolean argument "first" is to determine if between content should be generated. + // If first is false, the between content is generated; if first is true, between content is not generated. + // In the case of a multi-run string, between content should only be placed at the start of the string, not inside the string. + // When i > 0, we are dealing with a run in the middle of a multi-run string, so we pass value "true" for the argument "first" in order to suppress between content. + if (i > 0) + GenerateRunWithPossibleLink(settings, writingSystem, writer, style, text, linkTarget, rightToLeft, config, true, externalLink); + else + GenerateRunWithPossibleLink(settings, writingSystem, writer, style, text, linkTarget, rightToLeft, config, first, externalLink); } if (fieldValue.RunCount > 1) diff --git a/Src/xWorks/xWorksTests/LcmWordGeneratorTests.cs b/Src/xWorks/xWorksTests/LcmWordGeneratorTests.cs index ca2974f9c5..ddd9e3c3ff 100644 --- a/Src/xWorks/xWorksTests/LcmWordGeneratorTests.cs +++ b/Src/xWorks/xWorksTests/LcmWordGeneratorTests.cs @@ -567,6 +567,68 @@ public void GeneratePropertyData() // The property after text 'AF4' was written. Assert.True(outXml.Contains("AF4")); } + [Test] + public void EmbeddedStylesHaveNoExtraSpace() + { + var translationNode = new ConfigurableDictionaryNode + { + FieldDescription = "Translation", + DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetWsOptionsForLanguages(new[] { "en", "fr" }), + Between = "AREYOUCRAZY" + }; + var translationsNode = new ConfigurableDictionaryNode + { + FieldDescription = "TranslationsOC", + CSSClassNameOverride = "translationcontents", + Children = new List { translationNode } + }; + var exampleNode = new ConfigurableDictionaryNode + { + FieldDescription = "Example", + DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetWsOptionsForLanguages(new[] { "fr" }) + }; + var examplesNode = new ConfigurableDictionaryNode + { + FieldDescription = "ExamplesOS", + CSSClassNameOverride = "examplescontents", + Children = new List { exampleNode, translationsNode }, + Style = DictionaryNormal + }; + var sensesNode = new ConfigurableDictionaryNode + { + FieldDescription = "SensesOS", + CSSClassNameOverride = "senses", + DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetSenseNodeOptions(), + Children = new List { examplesNode }, + Style = DictionaryNormal + }; + var mainEntryNode = new ConfigurableDictionaryNode + { + FieldDescription = "LexEntry", + Children = new List { sensesNode }, + Style = DictionaryNormal + }; + CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode); + + const string example = "Jones and Schneider"; + const string translation = "Overwritten with actual SUT data"; + var testEntry = ConfiguredXHTMLGeneratorTests.CreateInterestingLexEntry(Cache); + var wsEn = Cache.WritingSystemFactory.GetWsFromStr("en"); + var wsFr = Cache.WritingSystemFactory.GetWsFromStr("fr"); + ConfiguredXHTMLGeneratorTests.AddExampleToSense(testEntry.SensesOS[0], example, Cache, wsFr, wsEn, translation); + var enTrans = MakeMuliStyleTss(new [] { "don't", "go", "between" }); + var frTrans = MakeMuliStyleTss(new[] { "aller", "entre", "eux" }); + testEntry.SensesOS[0].ExamplesOS[0].TranslationsOC.First().Translation.set_String(wsEn, enTrans); + testEntry.SensesOS[0].ExamplesOS[0].TranslationsOC.First().Translation.set_String(wsFr, frTrans); + + //SUT + var result = ConfiguredLcmGenerator.GenerateContentForEntry(testEntry, mainEntryNode, null, DefaultSettings, 0) as DocFragment; + var outXml = result.mainDocPart.RootElement.OuterXml; + // Verify that AREYOUCRAZY appears only once in the output. + var betweenCount = Regex.Matches(outXml, "AREYOUCRAZY").Count; + + Assert.That(betweenCount, Is.EqualTo(1)); // The between should not separate runs in a single translation + } [Test] public void ReferenceParagraphDisplayNames() @@ -853,5 +915,18 @@ public void GetFirstHeadwordStyle() Assert.True(firstHeadwordStyle == "Headword[lang='en']"); } + private ITsString MakeMuliStyleTss(IEnumerable content) + { + var wsEn = Cache.WritingSystemFactory.GetWsFromStr("en"); + var tsFact = TsStringUtils.TsStrFactory; + var builder = tsFact.GetIncBldr(); + var lastStyle = "Dictionary-Gloss-Char"; + foreach (var runContent in content) + { + builder.AppendTsString(TsStringUtils.MakeString(runContent, wsEn, lastStyle)); + lastStyle = lastStyle.Equals("Dictionary-Gloss-Char") ? "Dictionary-Normal-Char" : "Dictionary-Gloss-Char"; + } + return builder.GetString(); + } } }