From 8aec70380a65648f90406ef16b06338348dd286b Mon Sep 17 00:00:00 2001 From: Tony Hallett Date: Fri, 6 Oct 2023 20:49:01 +0100 Subject: [PATCH] add themed hover styling --- Shared Files/Resources/reportparts.xml | 3 +- .../ColourUtilities/LighnessApplier.cs | 337 ++++++++++++++++++ .../LuminanceContrastColourExtensions.cs | 36 ++ .../Core/ReportGenerator/IReportColours.cs | 1 + .../Core/ReportGenerator/JsThemeStyling.cs | 1 + .../Core/ReportGenerator/ReportColours.cs | 3 + .../ReportColoursExtensions.cs | 11 +- .../ReportGenerator/ReportGeneratorUtil.cs | 142 +++----- SharedProject/SharedProject.projitems | 2 + 9 files changed, 436 insertions(+), 100 deletions(-) create mode 100644 SharedProject/Core/ReportGenerator/ColourUtilities/LighnessApplier.cs create mode 100644 SharedProject/Core/ReportGenerator/ColourUtilities/LuminanceContrastColourExtensions.cs diff --git a/Shared Files/Resources/reportparts.xml b/Shared Files/Resources/reportparts.xml index a6b44552..d71d5ae8 100644 --- a/Shared Files/Resources/reportparts.xml +++ b/Shared Files/Resources/reportparts.xml @@ -18,7 +18,8 @@ - + + diff --git a/SharedProject/Core/ReportGenerator/ColourUtilities/LighnessApplier.cs b/SharedProject/Core/ReportGenerator/ColourUtilities/LighnessApplier.cs new file mode 100644 index 00000000..c44a3d6f --- /dev/null +++ b/SharedProject/Core/ReportGenerator/ColourUtilities/LighnessApplier.cs @@ -0,0 +1,337 @@ +using System; + +namespace FineCodeCoverage.Engine.ReportGenerator +{ + /* + Conversions from https://www.codeproject.com/Articles/19045/Manipulating-colors-in-NET-Part-1#hsb + This is potentially better https://github.com/tompazourek/Colourful/ + + */ + public struct RGB + { + /// + /// Gets an empty RGB structure; + /// + public static readonly RGB Empty = new RGB(); + + private int red; + private int green; + private int blue; + + public static bool operator ==(RGB item1, RGB item2) + { + return ( + item1.Red == item2.Red + && item1.Green == item2.Green + && item1.Blue == item2.Blue + ); + } + + public static bool operator !=(RGB item1, RGB item2) + { + return ( + item1.Red != item2.Red + || item1.Green != item2.Green + || item1.Blue != item2.Blue + ); + } + + /// + /// Gets or sets red value. + /// + public int Red + { + get + { + return red; + } + set + { + red = (value > 255) ? 255 : ((value < 0) ? 0 : value); + } + } + + /// + /// Gets or sets red value. + /// + public int Green + { + get + { + return green; + } + set + { + green = (value > 255) ? 255 : ((value < 0) ? 0 : value); + } + } + + /// + /// Gets or sets red value. + /// + public int Blue + { + get + { + return blue; + } + set + { + blue = (value > 255) ? 255 : ((value < 0) ? 0 : value); + } + } + + public RGB(int R, int G, int B) + { + this.red = (R > 255) ? 255 : ((R < 0) ? 0 : R); + this.green = (G > 255) ? 255 : ((G < 0) ? 0 : G); + this.blue = (B > 255) ? 255 : ((B < 0) ? 0 : B); + } + + public override bool Equals(Object obj) + { + if (obj == null || GetType() != obj.GetType()) return false; + + return (this == (RGB)obj); + } + + public override int GetHashCode() + { + return Red.GetHashCode() ^ Green.GetHashCode() ^ Blue.GetHashCode(); + } + } + public static class ColorConversion + { + /// + /// Converts HSL to RGB. + /// + /// Hue, must be in [0, 360]. + /// Saturation, must be in [0, 1]. + /// Luminance, must be in [0, 1]. + public static RGB HSLtoRGB(double h, double s, double l) + { + if (s == 0) + { + // achromatic color (gray scale) + return new RGB( + Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", + l * 255.0))), + Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", + l * 255.0))), + Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", + l * 255.0))) + ); + } + else + { + double q = (l < 0.5) ? (l * (1.0 + s)) : (l + s - (l * s)); + double p = (2.0 * l) - q; + + double Hk = h / 360.0; + double[] T = new double[3]; + T[0] = Hk + (1.0 / 3.0); // Tr + T[1] = Hk; // Tb + T[2] = Hk - (1.0 / 3.0); // Tg + + for (int i = 0; i < 3; i++) + { + if (T[i] < 0) T[i] += 1.0; + if (T[i] > 1) T[i] -= 1.0; + + if ((T[i] * 6) < 1) + { + T[i] = p + ((q - p) * 6.0 * T[i]); + } + else if ((T[i] * 2.0) < 1) //(1.0/6.0)<=T[i] && T[i]<0.5 + { + T[i] = q; + } + else if ((T[i] * 3.0) < 2) // 0.5<=T[i] && T[i]<(2.0/3.0) + { + T[i] = p + (q - p) * ((2.0 / 3.0) - T[i]) * 6.0; + } + else T[i] = p; + } + + return new RGB( + Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", + T[0] * 255.0))), + Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", + T[1] * 255.0))), + Convert.ToInt32(Double.Parse(String.Format("{0:0.00}", + T[2] * 255.0))) + ); + } + } + + public static HSL RGBtoHSL(int red, int green, int blue) + { + double h = 0, s = 0, l = 0; + + // normalize red, green, blue values + double r = (double)red / 255.0; + double g = (double)green / 255.0; + double b = (double)blue / 255.0; + + double max = Math.Max(r, Math.Max(g, b)); + double min = Math.Min(r, Math.Min(g, b)); + + // hue + if (max == min) + { + h = 0; // undefined + } + else if (max == r && g >= b) + { + h = 60.0 * (g - b) / (max - min); + } + else if (max == r && g < b) + { + h = 60.0 * (g - b) / (max - min) + 360.0; + } + else if (max == g) + { + h = 60.0 * (b - r) / (max - min) + 120.0; + } + else if (max == b) + { + h = 60.0 * (r - g) / (max - min) + 240.0; + } + + // luminance + l = (max + min) / 2.0; + + // saturation + if (l == 0 || max == min) + { + s = 0; + } + else if (0 < l && l <= 0.5) + { + s = (max - min) / (max + min); + } + else if (l > 0.5) + { + s = (max - min) / (2 - (max + min)); //(max-min > 0)? + } + + return new HSL( + Double.Parse(String.Format("{0:0.##}", h)), + Double.Parse(String.Format("{0:0.##}", s)), + Double.Parse(String.Format("{0:0.##}", l)) + ); + } + } + + public struct HSL + { + /// + /// Gets an empty HSL structure; + /// + public static readonly HSL Empty = new HSL(); + + private double hue; + private double saturation; + private double luminance; + + public static bool operator ==(HSL item1, HSL item2) + { + return ( + item1.Hue == item2.Hue + && item1.Saturation == item2.Saturation + && item1.Luminance == item2.Luminance + ); + } + + public static bool operator !=(HSL item1, HSL item2) + { + return ( + item1.Hue != item2.Hue + || item1.Saturation != item2.Saturation + || item1.Luminance != item2.Luminance + ); + } + + /// + /// Gets or sets the hue component. + /// + public double Hue + { + get + { + return hue; + } + set + { + hue = (value > 360) ? 360 : ((value < 0) ? 0 : value); + } + } + + /// + /// Gets or sets saturation component. + /// + public double Saturation + { + get + { + return saturation; + } + set + { + saturation = (value > 1) ? 1 : ((value < 0) ? 0 : value); + } + } + + /// + /// Gets or sets the luminance component. + /// + public double Luminance + { + get + { + return luminance; + } + set + { + luminance = (value > 1) ? 1 : ((value < 0) ? 0 : value); + } + } + + /// + /// Creates an instance of a HSL structure. + /// + /// Hue value. + /// Saturation value. + /// Lightness value. + public HSL(double h, double s, double l) + { + this.hue = (h > 360) ? 360 : ((h < 0) ? 0 : h); + this.saturation = (s > 1) ? 1 : ((s < 0) ? 0 : s); + this.luminance = (l > 1) ? 1 : ((l < 0) ? 0 : l); + } + + public override bool Equals(Object obj) + { + if (obj == null || GetType() != obj.GetType()) return false; + + return (this == (HSL)obj); + } + + public override int GetHashCode() + { + return Hue.GetHashCode() ^ Saturation.GetHashCode() ^ + Luminance.GetHashCode(); + } + } + public static class LightenssApplier + { + public static System.Drawing.Color Swap(System.Drawing.Color lightnessColor, System.Drawing.Color applyToColor) + { + var hsl = ColorConversion.RGBtoHSL(lightnessColor.R, lightnessColor.G, lightnessColor.B); + var hsl2 = ColorConversion.RGBtoHSL(applyToColor.R, applyToColor.G, applyToColor.B); + hsl2.Luminance = hsl.Luminance; + var rgb = ColorConversion.HSLtoRGB(hsl2.Hue, hsl2.Saturation, hsl2.Luminance); + return System.Drawing.Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue); + } + } +} diff --git a/SharedProject/Core/ReportGenerator/ColourUtilities/LuminanceContrastColourExtensions.cs b/SharedProject/Core/ReportGenerator/ColourUtilities/LuminanceContrastColourExtensions.cs new file mode 100644 index 00000000..5adde47a --- /dev/null +++ b/SharedProject/Core/ReportGenerator/ColourUtilities/LuminanceContrastColourExtensions.cs @@ -0,0 +1,36 @@ +using System; + +namespace FineCodeCoverage.Engine.ReportGenerator +{ + internal static class LuminanceContrastColourExtensions + { + public static double Contrast(this System.Drawing.Color color, System.Drawing.Color color2) + { + var l1 = color.Luminance(); + var l2 = color2.Luminance(); + return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05); + + } + + public static double Luminance(this System.Drawing.Color color) + { + return Luminance(color.R, color.G, color.B); + } + + private static double Luminance(int r, int g, int b) + { + var lr = LuminanceX(r); + var lg = LuminanceX(g); + var lb = LuminanceX(b); + return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb; + + } + + private static double LuminanceX(int x) + { + x /= 255; + return x <= 0.03928 ? x / 12.92 : Math.Pow((x + 0.055) / 1.055, 2.4); + + } + } +} diff --git a/SharedProject/Core/ReportGenerator/IReportColours.cs b/SharedProject/Core/ReportGenerator/IReportColours.cs index 1798e0f7..4a7392c3 100644 --- a/SharedProject/Core/ReportGenerator/IReportColours.cs +++ b/SharedProject/Core/ReportGenerator/IReportColours.cs @@ -24,6 +24,7 @@ internal interface IReportColours Color CoverageTableInactiveSortColour { get; } Color CoverageTableRowHoverBackgroundColour { get; } + Color CoverageTableRowHoverColour { get; } Color DivHeaderBackgroundColour { get; } diff --git a/SharedProject/Core/ReportGenerator/JsThemeStyling.cs b/SharedProject/Core/ReportGenerator/JsThemeStyling.cs index e3117268..1016dd67 100644 --- a/SharedProject/Core/ReportGenerator/JsThemeStyling.cs +++ b/SharedProject/Core/ReportGenerator/JsThemeStyling.cs @@ -17,6 +17,7 @@ public class JsThemeStyling public string LinkColour; public string CoverageTableHeaderFontColour; public string CoverageTableRowHoverBackgroundColour; + public string CoverageTableRowHoverColour; public string DivHeaderBackgroundColour; public string TabBackgroundColour; public string HeaderFontColour; diff --git a/SharedProject/Core/ReportGenerator/ReportColours.cs b/SharedProject/Core/ReportGenerator/ReportColours.cs index 09c23940..932fa024 100644 --- a/SharedProject/Core/ReportGenerator/ReportColours.cs +++ b/SharedProject/Core/ReportGenerator/ReportColours.cs @@ -25,6 +25,8 @@ internal class ReportColours : IReportColours public Color CoverageTableRowHoverBackgroundColour { get; set; } + public Color CoverageTableRowHoverColour { get; set; } + public Color DivHeaderBackgroundColour { get; set; } public Color FontColour { get; set; } @@ -88,6 +90,7 @@ internal class ReportColours : IReportColours public Color ButtonHoverTextColour { get; set; } public Color ButtonPressedTextColour { get; set; } + } } diff --git a/SharedProject/Core/ReportGenerator/ReportColoursExtensions.cs b/SharedProject/Core/ReportGenerator/ReportColoursExtensions.cs index c1f96aca..79c0084a 100644 --- a/SharedProject/Core/ReportGenerator/ReportColoursExtensions.cs +++ b/SharedProject/Core/ReportGenerator/ReportColoursExtensions.cs @@ -6,7 +6,7 @@ namespace FineCodeCoverage.Engine.ReportGenerator { internal static class ReportColoursExtensions { - private class ColourReflection + private class ColourReflection { public PropertyInfo ReportColoursPropertyInfo { get; set; } public FieldInfo JsThemeStylingFieldInfo { get; set; } @@ -50,5 +50,14 @@ public static string ToJsColour(this System.Drawing.Color colour) { return $"rgba({colour.R},{colour.G},{colour.B},{colour.A})"; } + + public static System.Drawing.Color ToColor(string jsColor) + { + var rgba = jsColor.Replace("rgba(", "").Replace(")", "").Split(','); + return System.Drawing.Color.FromArgb(int.Parse(rgba[3]), int.Parse(rgba[0]), int.Parse(rgba[1]), int.Parse(rgba[2])); + + } + } + } diff --git a/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs b/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs index f268eecc..a60cbae5 100644 --- a/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs +++ b/SharedProject/Core/ReportGenerator/ReportGeneratorUtil.cs @@ -21,6 +21,8 @@ namespace FineCodeCoverage.Engine.ReportGenerator { + + interface IReportGeneratorUtil { void Initialize(string appDataFolder, CancellationToken cancellationToken); @@ -56,7 +58,6 @@ internal partial class ReportGeneratorUtil : private const string zipPrefix = "reportGenerator"; private const string zipDirectoryName = "reportGenerator"; - private const string ThemeChangedJSFunctionName = "themeChanged"; private const string CoverageLogJSFunctionName = "coverageLog"; private const string CoverageLogTabName = "Coverage Log"; private const string ShowFCCWorkingJSFunctionName = "showFCCWorking"; @@ -224,6 +225,19 @@ async Task run(string outputReportType, string inputReports) return reportGeneratorResult; } + private string GetRowHoverLinkColour(bool useLightness = true) + { + if (useLightness) + { + return LightenssApplier.Swap( + ReportColoursExtensions.ToColor(jsReportColours.CoverageTableRowHoverColour), + ReportColoursExtensions.ToColor(jsReportColours.LinkColour) + ).ToJsColour(); + } + + return jsReportColours.CoverageTableRowHoverColour; + } + private void SetInitialTheme(HtmlAgilityPack.HtmlDocument document) { var backgroundColor = jsReportColours.BackgroundColour; @@ -270,9 +284,21 @@ Other option overviewHeaderLinks.Style.Color = jsReportColours.CoverageTableHeaderFontColour; var overviewTrHoverRule = styleRules.First(r => r.SelectorText == ".overview tr:hover"); - overviewTrHoverRule.Style.Background = jsReportColours.CoverageTableRowHoverBackgroundColour; - var expandCollapseIconColor = ReportColours.CoverageTableExpandCollapseIconColour; + /* + Alternative is lighten / darken the background color + ControlPaint.Dark / Light is percentage based - so we can't use it here + */ + + overviewTrHoverRule.Style.Background = jsReportColours.CoverageTableRowHoverBackgroundColour; + + var trHoverTdRule = stylesheet.Add(RuleType.Style); + trHoverTdRule.Text = $".overview tr:hover td {{color:{jsReportColours.CoverageTableRowHoverColour}}}"; + + var trHoverARule = stylesheet.Add(RuleType.Style); + trHoverARule.Text = $".overview tr:hover td a {{color:{GetRowHoverLinkColour()}}}"; + + var expandCollapseIconColor = ReportColours.CoverageTableExpandCollapseIconColour; plusBase64ReportImage.FillSvg(styleRules, expandCollapseIconColor.ToJsColour()); minusBase64ReportImage.FillSvg(styleRules, expandCollapseIconColor.ToJsColour()); @@ -877,6 +903,19 @@ private string HideCyclomaticComplexityLink() } + /* + whilst hacking at the report generator html ! can use this to save to html and inspect with chrome dev tools + */ + private string AddCopyDocToClipboardButtonIfRequired(bool required = false) + { + var code = @" + + +"; + return required ? code : ""; + + } + public string ProcessUnifiedHtml(string htmlForProcessing, string reportOutputFolder) { previousFontSizeName = GetFontNameSize(); @@ -1071,101 +1110,7 @@ function getStyleSheetById(id){{ generalStyle.setProperty('font-family',parts[0]); generalStyle.setProperty('font-size',parts[1]); }} - function {ThemeChangedJSFunctionName}(theme){{ - var fccMediaStylesheet = getStyleSheetById('fccMediaStyle'); - var highContrastRule = fccMediaStylesheet.cssRules[0] - var highContrastRules = highContrastRule.cssRules - getStyleBySelector(highContrastRules,'table.coverage > td.gray').setProperty('background-color',theme.{nameof(JsThemeStyling.GrayCoverageColour)}); - - var fccStyleSheet1Rules = getStyleSheetById('fccStyle1').cssRules; - var buttonStyle = getStyleBySelector(fccStyleSheet1Rules,'button'); - buttonStyle.setProperty('color',theme.{nameof(JsThemeStyling.ButtonTextColour)}); - buttonStyle.setProperty('background',theme.{nameof(JsThemeStyling.ButtonColour)}); - buttonStyle.setProperty('border-color',theme.{nameof(JsThemeStyling.ButtonBorderColour)}); - var buttonHoverStyle = getStyleBySelector(fccStyleSheet1Rules,'button:hover'); - buttonHoverStyle.setProperty('color',theme.{nameof(JsThemeStyling.ButtonHoverTextColour)}); - buttonHoverStyle.setProperty('background',theme.{nameof(JsThemeStyling.ButtonHoverColour)}); - buttonHoverStyle.setProperty('border-color',theme.{nameof(JsThemeStyling.ButtonBorderHoverColour)}); - var buttonPressedStyle = getStyleBySelector(fccStyleSheet1Rules,'button:active'); - buttonPressedStyle.setProperty('color',theme.{nameof(JsThemeStyling.ButtonPressedTextColour)}); - buttonPressedStyle.setProperty('background',theme.{nameof(JsThemeStyling.ButtonPressedColour)}); - buttonPressedStyle.setProperty('border-color',theme.{nameof(JsThemeStyling.ButtonBorderPressedColour)}); - - - var rangeInputFillLower = getStyleBySelector(fccStyleSheet1Rules, 'input[type=range]::-ms-fill-lower'); - rangeInputFillLower.setProperty('background',theme.{nameof(JsThemeStyling.SliderLeftColour)}); - var rangeInputFillUpper = getStyleBySelector(fccStyleSheet1Rules, 'input[type=range]::-ms-fill-upper'); - rangeInputFillUpper.setProperty('background',theme.{nameof(JsThemeStyling.SliderRightColour)}); - var rangeInputThumb = getStyleBySelector(fccStyleSheet1Rules, 'input[type=range]::-ms-thumb'); - rangeInputThumb.setProperty('background',theme.{nameof(JsThemeStyling.SliderThumbColour)}); - rangeInputThumb.setProperty('border',theme.{nameof(JsThemeStyling.SliderThumbColour)}); - - var scrollBarStyle = getStyleBySelector(fccStyleSheet1Rules,'body, html'); - scrollBarStyle.setProperty('scrollbar-arrow-color',theme.{nameof(JsThemeStyling.ScrollBarArrowColour)}); - scrollBarStyle.setProperty('scrollbar-track-color',theme.{nameof(JsThemeStyling.ScrollBarTrackColour)}); - scrollBarStyle.setProperty('scrollbar-face-color',theme.{nameof(JsThemeStyling.ScrollBarThumbColour)}); - scrollBarStyle.setProperty('scrollbar-shadow-color',theme.{nameof(JsThemeStyling.ScrollBarThumbColour)}); - scrollBarStyle.setProperty('scrollbar-highlight-color',theme.{nameof(JsThemeStyling.ScrollBarThumbColour)}); - scrollBarStyle.setProperty('scrollbar-3dlight-color',theme.{nameof(JsThemeStyling.ScrollBarThumbColour)}); - scrollBarStyle.setProperty('scrollbar-darkshadow-color',theme.{nameof(JsThemeStyling.ScrollBarThumbColour)}); - - getStyleBySelector(fccStyleSheet1Rules,'*, body').setProperty('color',theme.{nameof(JsThemeStyling.FontColour)}); - var textStyle = getStyleBySelector(fccStyleSheet1Rules,'input[type=text]'); - textStyle.setProperty('color',theme.{nameof(JsThemeStyling.TextBoxTextColour)}); - textStyle.setProperty('background-color',theme.{nameof(JsThemeStyling.TextBoxColour)}); - textStyle.setProperty('border-color',theme.{nameof(JsThemeStyling.TextBoxBorderColour)}); - - var comboStyle = getStyleBySelector(fccStyleSheet1Rules,'select'); - comboStyle.setProperty('color',theme.{nameof(JsThemeStyling.ComboBoxTextColour)}); - comboStyle.setProperty('background-color',theme.{nameof(JsThemeStyling.ComboBoxColour)}); - comboStyle.setProperty('border-color',theme.{nameof(JsThemeStyling.ComboBoxBorderColour)}); - - var fccStyleSheet2Rules = getStyleSheetById('fccStyle2').cssRules; - getStyleBySelector(fccStyleSheet2Rules,'#divHeader').setProperty('background-color',theme.{nameof(JsThemeStyling.DivHeaderBackgroundColour)}); - var headerTabsStyle = getStyleBySelector(fccStyleSheet2Rules,'table#headerTabs td'); - headerTabsStyle.setProperty('color',theme.{nameof(JsThemeStyling.HeaderFontColour)}); - headerTabsStyle.setProperty('border-color',theme.{nameof(JsThemeStyling.HeaderBorderColour)}); - getStyleBySelector(fccStyleSheet2Rules,'table#headerTabs td.tab').setProperty('background-color',theme.{nameof(JsThemeStyling.TabBackgroundColour)}); - - var mainStyle = document.styleSheets[0]; - var mainRules = mainStyle.cssRules; - - getStyleBySelector(mainRules,'.gray').setProperty('background-color',theme.{nameof(JsThemeStyling.GrayCoverageColour)}); - - getStyleBySelector(mainRules,'html').setProperty('background-color',theme.{nameof(JsThemeStyling.BackgroundColour)}); - getStyleBySelector(mainRules,'.container').setProperty('background-color',theme.{nameof(JsThemeStyling.BackgroundColour)}); - - var overviewTableBorder = '1px solid ' + theme.{nameof(JsThemeStyling.TableBorderColour)}; - var overviewStyle = getStyleBySelector(mainRules,'.overview'); - overviewStyle.setProperty('border',overviewTableBorder); - var overviewThStyle = getStyleBySelector(mainRules,'.overview th'); - overviewThStyle.setProperty('background-color',theme.{nameof(JsThemeStyling.BackgroundColour)}); - overviewThStyle.setProperty('border',overviewTableBorder); - var overviewTdStyle = getStyleBySelector(mainRules,'.overview td'); - overviewTdStyle.setProperty('border',overviewTableBorder); - - var overviewHeaderLinksStyle = getStyleBySelector(mainRules,'.overview th a'); - overviewHeaderLinksStyle.setProperty('color',theme.{nameof(JsThemeStyling.CoverageTableHeaderFontColour)}); - - var overviewTrHoverStyle = getStyleBySelector(mainRules,'.overview tr:hover'); - overviewTrHoverStyle.setProperty('background',theme.{nameof(JsThemeStyling.CoverageTableRowHoverBackgroundColour)}); - - var linkStyle = getStyleBySelector(mainRules,'a'); - var linkHoverStyle = getStyleBySelector(mainRules,'a:hover'); - linkStyle.setProperty('color',theme.{nameof(JsThemeStyling.LinkColour)}); - linkHoverStyle.setProperty('color',theme.{nameof(JsThemeStyling.LinkColour)}); - - var iconPlusStyle = getStyleBySelector(mainRules,'.icon-plus'); - iconPlusStyle.setProperty('background-image',theme.{nameof(JsThemeStyling.PlusBase64)}); - var iconMinusStyle = getStyleBySelector(mainRules,'.icon-minus'); - iconMinusStyle.setProperty('background-image',theme.{nameof(JsThemeStyling.MinusBase64)}); - var iconDownActiveStyle = getStyleBySelector(mainRules,'.icon-down-dir_active'); - iconDownActiveStyle.setProperty('background-image',theme.{nameof(JsThemeStyling.DownActiveBase64)}); - var iconDownInactiveStyle = getStyleBySelector(mainRules,'.icon-down-dir'); - iconDownInactiveStyle.setProperty('background-image',theme.{nameof(JsThemeStyling.DownInactiveBase64)}); - var iconUpActiveStyle = getStyleBySelector(mainRules,'.icon-up-dir_active'); - iconUpActiveStyle.setProperty('background-image',theme.{nameof(JsThemeStyling.UpActiveBase64)}); - }} + var htmlExtension = '.html'; var eventListener = function (element, event, func) {{ @@ -1466,6 +1411,7 @@ Risk Hotspots + {AddCopyDocToClipboardButtonIfRequired()} "); if (!showBranchCoverage) diff --git a/SharedProject/SharedProject.projitems b/SharedProject/SharedProject.projitems index 002e699a..32571395 100644 --- a/SharedProject/SharedProject.projitems +++ b/SharedProject/SharedProject.projitems @@ -118,6 +118,8 @@ + +