/// <summary> /// Shift any translationGroup level style setting to child editable divs that lack a style. /// This is motivated by the fact HTML/CSS underlining cannot be turned off in child nodes. /// So if underlining is enabled for Normal, everything everywhere would be underlined /// regardless of style or immediate character formatting. If a style sets underlining /// on, then immediate character formatting cannot turn it off anywhere in a text box that /// uses that style. See https://silbloom.myjetbrains.com/youtrack/issue/BL-6282. /// </summary> private static void FixGroupStyleSettings(XmlNode pageDiv) { foreach ( XmlElement groupElement in pageDiv.SafeSelectNodes("descendant-or-self::*[contains(@class,'bloom-translationGroup')]")) { var groupStyle = HtmlDom.GetStyle(groupElement); if (String.IsNullOrEmpty(groupStyle)) { continue; } // Copy the group's style setting to any child div with the bloom-editable class that lacks one. // Then remove the group style if it does have any child divs with the bloom-editable class. bool hasInternalEditableDiv = false; foreach (XmlElement element in groupElement.SafeSelectNodes("child::div[contains(@class, 'bloom-editable')]")) { var divStyle = HtmlDom.GetStyle(element); if (String.IsNullOrEmpty(divStyle)) { HtmlDom.AddClass(element, groupStyle); } hasInternalEditableDiv = true; } if (hasInternalEditableDiv) { HtmlDom.RemoveClass(groupElement, groupStyle); } } }
private static void UpdateContentLanguageClassesOnElement(XmlElement e, Dictionary <string, string> contentLanguages, BookData bookData, string contentLanguageIso2, string contentLanguageIso3, string[] dataDefaultLanguages) { HtmlDom.RemoveClassesBeginingWith(e, "bloom-content"); var lang = e.GetAttribute("lang"); //These bloom-content* classes are used by some stylesheet rules, primarily to boost the font-size of some languages. //Enhance: this is too complex; the semantics of these overlap with each other and with bloom-visibility-code-on, and with data-language-order. //It would be better to have non-overlapping things; 1 for order, 1 for visibility, one for the lang's role in this collection. string orderClass; if (contentLanguages.TryGetValue(lang, out orderClass)) { HtmlDom.AddClass(e, orderClass); //bloom-content1, bloom-content2, bloom-content3 } //Enhance: it's even more likely that we can get rid of these by replacing them with bloom-content2, bloom-content3 if (lang == bookData.MetadataLanguage1IsoCode) { HtmlDom.AddClass(e, "bloom-contentNational1"); } if (lang == bookData.Language3IsoCode) { HtmlDom.AddClass(e, "bloom-contentNational2"); } HtmlDom.RemoveClassesBeginingWith(e, "bloom-visibility-code"); if (ShouldNormallyShowEditable(lang, dataDefaultLanguages, contentLanguageIso2, contentLanguageIso3, bookData)) { HtmlDom.AddClass(e, "bloom-visibility-code-on"); } UpdateRightToLeftSetting(bookData, e, lang); }
/// <summary> /// We stick 'contentLanguage2' and 'contentLanguage3' classes on editable things in bilingual and trilingual books /// </summary> public static void UpdateContentLanguageClasses(XmlNode elementOrDom, string vernacularIso, string national1Iso, string national2Iso, string contentLanguageIso2, string contentLanguageIso3) { var multilingualClass = "bloom-monolingual"; var contentLanguages = new Dictionary <string, string>(); contentLanguages.Add(vernacularIso, "bloom-content1"); if (!String.IsNullOrEmpty(contentLanguageIso2) && vernacularIso != contentLanguageIso2) { multilingualClass = "bloom-bilingual"; contentLanguages.Add(contentLanguageIso2, "bloom-content2"); } if (!String.IsNullOrEmpty(contentLanguageIso3) && vernacularIso != contentLanguageIso3 && contentLanguageIso2 != contentLanguageIso3) { multilingualClass = "bloom-trilingual"; Debug.Assert(!String.IsNullOrEmpty(contentLanguageIso2), "shouldn't have a content3 lang with no content2 lang"); contentLanguages.Add(contentLanguageIso3, "bloom-content3"); } //Stick a class in the page div telling the stylesheet how many languages we are displaying (only makes sense for content pages, in Jan 2012). foreach (XmlElement pageDiv in elementOrDom.SafeSelectNodes("descendant-or-self::div[contains(@class,'bloom-page') and not(contains(@class,'bloom-frontMatter')) and not(contains(@class,'bloom-backMatter'))]")) { HtmlDom.RemoveClassesBeginingWith(pageDiv, "bloom-monolingual"); HtmlDom.RemoveClassesBeginingWith(pageDiv, "bloom-bilingual"); HtmlDom.RemoveClassesBeginingWith(pageDiv, "bloom-trilingual"); HtmlDom.AddClassIfMissing(pageDiv, multilingualClass); } foreach (XmlElement group in elementOrDom.SafeSelectNodes(".//*[contains(@class,'bloom-translationGroup')]")) { var isXMatter = @group.SafeSelectNodes("ancestor::div[contains(@class,'bloom-frontMatter') or contains(@class,'bloom-backMatter')]").Count > 0; foreach (XmlElement e in @group.SafeSelectNodes(".//textarea | .//div")) //nb: we don't necessarily care that a div is editable or not { var lang = e.GetAttribute("lang"); HtmlDom.RemoveClassesBeginingWith(e, "bloom-content"); //they might have been a given content lang before, but not now if (isXMatter && lang == national1Iso) { HtmlDom.AddClass(e, "bloom-contentNational1"); } if (isXMatter && !String.IsNullOrEmpty(national2Iso) && lang == national2Iso) { HtmlDom.AddClass(e, "bloom-contentNational2"); } foreach (var language in contentLanguages) { if (lang == language.Key) { HtmlDom.AddClass(e, language.Value); break; //don't check the other languages } } } } }
private static void UpdateContentLanguageClassesOnElement(XmlElement e, Dictionary <string, string> contentLanguages, BookData bookData, string contentLanguageIso2, string contentLanguageIso3, string[] dataDefaultLanguages) { HtmlDom.RemoveClassesBeginingWith(e, "bloom-content"); var lang = e.GetAttribute("lang"); //These bloom-content* classes are used by some stylesheet rules, primarily to boost the font-size of some languages. //Enhance: this is too complex; the semantics of these overlap with each other and with bloom-visibility-code-on, and with data-language-order. //It would be better to have non-overlapping things; 1 for order, 1 for visibility, one for the lang's role in this collection. string orderClass; if (contentLanguages.TryGetValue(lang, out orderClass)) { HtmlDom.AddClass(e, orderClass); //bloom-content1, bloom-content2, bloom-content3 } //Enhance: it's even more likely that we can get rid of these by replacing them with bloom-content2, bloom-content3 if (lang == bookData.MetadataLanguage1IsoCode) { HtmlDom.AddClass(e, "bloom-contentNational1"); } // It's not clear that this class should be applied to blocks where lang == bookData.Language3IsoCode. // I (JohnT) added lang == bookData.MetadataLanguage2IsoCode while dealing with BL-10893 // but am reluctant to remove the old code as something might depend on it. I believe it is (nearly?) // always true that if we have Language3IsoCode at all, it will be equal to MetadataLanguage2IsoCode, // so at least for now it probably makes no difference. In our next major reworking of language codes, // hopefully we can make this distinction clearer and remove Language3IsoCode here. if (lang == bookData.Language3IsoCode || lang == bookData.MetadataLanguage2IsoCode) { HtmlDom.AddClass(e, "bloom-contentNational2"); } HtmlDom.RemoveClassesBeginingWith(e, "bloom-visibility-code"); if (ShouldNormallyShowEditable(lang, dataDefaultLanguages, contentLanguageIso2, contentLanguageIso3, bookData)) { HtmlDom.AddClass(e, "bloom-visibility-code-on"); } UpdateRightToLeftSetting(bookData, e, lang); }
/// <summary> /// We stick 'contentLanguage2' and 'contentLanguage3' classes on editable things in bilingual and trilingual books /// </summary> public static void UpdateContentLanguageClasses(XmlNode elementOrDom, CollectionSettings settings, string vernacularIso, string contentLanguageIso2, string contentLanguageIso3) { var multilingualClass = "bloom-monolingual"; var contentLanguages = new Dictionary <string, string>(); contentLanguages.Add(vernacularIso, "bloom-content1"); if (!String.IsNullOrEmpty(contentLanguageIso2) && vernacularIso != contentLanguageIso2) { multilingualClass = "bloom-bilingual"; contentLanguages.Add(contentLanguageIso2, "bloom-content2"); } if (!String.IsNullOrEmpty(contentLanguageIso3) && vernacularIso != contentLanguageIso3 && contentLanguageIso2 != contentLanguageIso3) { multilingualClass = "bloom-trilingual"; contentLanguages.Add(contentLanguageIso3, "bloom-content3"); Debug.Assert(!String.IsNullOrEmpty(contentLanguageIso2), "shouldn't have a content3 lang with no content2 lang"); } //Stick a class in the page div telling the stylesheet how many languages we are displaying (only makes sense for content pages, in Jan 2012). foreach ( XmlElement pageDiv in elementOrDom.SafeSelectNodes( "descendant-or-self::div[contains(@class,'bloom-page') and not(contains(@class,'bloom-frontMatter')) and not(contains(@class,'bloom-backMatter'))]") ) { HtmlDom.RemoveClassesBeginingWith(pageDiv, "bloom-monolingual"); HtmlDom.RemoveClassesBeginingWith(pageDiv, "bloom-bilingual"); HtmlDom.RemoveClassesBeginingWith(pageDiv, "bloom-trilingual"); HtmlDom.AddClassIfMissing(pageDiv, multilingualClass); } // This is the "code" part of the visibility system: https://goo.gl/EgnSJo foreach (XmlElement group in elementOrDom.SafeSelectNodes(".//*[contains(@class,'bloom-translationGroup')]")) { var dataDefaultLanguages = HtmlDom.GetAttributeValue(group, "data-default-languages").Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); //nb: we don't necessarily care that a div is editable or not foreach (XmlElement e in @group.SafeSelectNodes(".//textarea | .//div")) { HtmlDom.RemoveClassesBeginingWith(e, "bloom-content"); var lang = e.GetAttribute("lang"); //These bloom-content* classes are used by some stylesheet rules, primarily to boost the font-size of some languages. //Enhance: this is too complex; the semantics of these overlap with each other and with bloom-visibility-code-on, and with data-language-order. //It would be better to have non-overlapping things; 1 for order, 1 for visibility, one for the lang's role in this collection. string orderClass; if (contentLanguages.TryGetValue(lang, out orderClass)) { HtmlDom.AddClass(e, orderClass); //bloom-content1, bloom-content2, bloom-content3 } //Enhance: it's even more likely that we can get rid of these by replacing them with bloom-content2, bloom-content3 if (lang == settings.Language2Iso639Code) { HtmlDom.AddClass(e, "bloom-contentNational1"); } if (lang == settings.Language3Iso639Code) { HtmlDom.AddClass(e, "bloom-contentNational2"); } HtmlDom.RemoveClassesBeginingWith(e, "bloom-visibility-code"); if (ShouldNormallyShowEditable(lang, dataDefaultLanguages, contentLanguageIso2, contentLanguageIso3, settings)) { HtmlDom.AddClass(e, "bloom-visibility-code-on"); } UpdateRightToLeftSetting(settings, e, lang); } } }