mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-04 10:35:27 +08:00 
			
		
		
		
	Add link support for supported terminals
Also refactors the code quite a bit, to make it a bit more easier to add features like this in the future. Closes #75
This commit is contained in:
		
				
					committed by
					
						
						Patrik Svensson
					
				
			
			
				
	
			
			
			
						parent
						
							1601ef24b3
						
					
				
				
					commit
					504746c5dc
				
			@@ -1,3 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console.Internal
 | 
			
		||||
@@ -5,40 +6,59 @@ namespace Spectre.Console.Internal
 | 
			
		||||
    internal static class AnsiBuilder
 | 
			
		||||
    {
 | 
			
		||||
        public static string GetAnsi(
 | 
			
		||||
            ColorSystem system,
 | 
			
		||||
            Capabilities capabilities,
 | 
			
		||||
            string text,
 | 
			
		||||
            Decoration decoration,
 | 
			
		||||
            Color foreground,
 | 
			
		||||
            Color background)
 | 
			
		||||
            Color background,
 | 
			
		||||
            string? link)
 | 
			
		||||
        {
 | 
			
		||||
            var codes = AnsiDecorationBuilder.GetAnsiCodes(decoration);
 | 
			
		||||
 | 
			
		||||
            // Got foreground?
 | 
			
		||||
            if (foreground != Color.Default)
 | 
			
		||||
            {
 | 
			
		||||
                codes = codes.Concat(AnsiColorBuilder.GetAnsiCodes(system, foreground, foreground: true));
 | 
			
		||||
                codes = codes.Concat(
 | 
			
		||||
                    AnsiColorBuilder.GetAnsiCodes(
 | 
			
		||||
                        capabilities.ColorSystem,
 | 
			
		||||
                        foreground,
 | 
			
		||||
                        true));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Got background?
 | 
			
		||||
            if (background != Color.Default)
 | 
			
		||||
            {
 | 
			
		||||
                codes = codes.Concat(AnsiColorBuilder.GetAnsiCodes(system, background, foreground: false));
 | 
			
		||||
                codes = codes.Concat(
 | 
			
		||||
                    AnsiColorBuilder.GetAnsiCodes(
 | 
			
		||||
                        capabilities.ColorSystem,
 | 
			
		||||
                        background,
 | 
			
		||||
                        false));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var result = codes.ToArray();
 | 
			
		||||
            if (result.Length == 0)
 | 
			
		||||
            if (result.Length == 0 && link == null)
 | 
			
		||||
            {
 | 
			
		||||
                return text;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var lol = string.Concat(
 | 
			
		||||
                "\u001b[",
 | 
			
		||||
                string.Join(";", result),
 | 
			
		||||
                "m",
 | 
			
		||||
                text,
 | 
			
		||||
                "\u001b[0m");
 | 
			
		||||
            var ansiCodes = string.Join(";", result);
 | 
			
		||||
            var ansi = result.Length > 0
 | 
			
		||||
                ? $"\u001b[{ansiCodes}m{text}\u001b[0m"
 | 
			
		||||
                : text;
 | 
			
		||||
 | 
			
		||||
            return lol;
 | 
			
		||||
            if (link != null && !capabilities.LegacyConsole)
 | 
			
		||||
            {
 | 
			
		||||
                // Empty links means we should take the URL from the text.
 | 
			
		||||
                if (link.Equals(Constants.EmptyLink, StringComparison.Ordinal))
 | 
			
		||||
                {
 | 
			
		||||
                    link = text;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var linkId = Math.Abs(link.GetDeterministicHashCode());
 | 
			
		||||
                ansi = $"\u001b]8;id={linkId};{link}\u001b\\{ansi}\u001b]8;;\u001b\\";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return ansi;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,13 +7,9 @@ namespace Spectre.Console.Internal
 | 
			
		||||
    internal sealed class AnsiConsoleRenderer : IAnsiConsole
 | 
			
		||||
    {
 | 
			
		||||
        private readonly TextWriter _out;
 | 
			
		||||
        private readonly ColorSystem _system;
 | 
			
		||||
 | 
			
		||||
        public Capabilities Capabilities { get; }
 | 
			
		||||
        public Encoding Encoding { get; }
 | 
			
		||||
        public Decoration Decoration { get; set; }
 | 
			
		||||
        public Color Foreground { get; set; }
 | 
			
		||||
        public Color Background { get; set; }
 | 
			
		||||
 | 
			
		||||
        public int Width
 | 
			
		||||
        {
 | 
			
		||||
@@ -44,28 +40,26 @@ namespace Spectre.Console.Internal
 | 
			
		||||
        public AnsiConsoleRenderer(TextWriter @out, ColorSystem system, bool legacyConsole)
 | 
			
		||||
        {
 | 
			
		||||
            _out = @out ?? throw new ArgumentNullException(nameof(@out));
 | 
			
		||||
            _system = system;
 | 
			
		||||
 | 
			
		||||
            Capabilities = new Capabilities(true, system, legacyConsole);
 | 
			
		||||
            Encoding = @out.IsStandardOut() ? System.Console.OutputEncoding : Encoding.UTF8;
 | 
			
		||||
            Foreground = Color.Default;
 | 
			
		||||
            Background = Color.Default;
 | 
			
		||||
            Decoration = Decoration.None;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Write(string text)
 | 
			
		||||
        public void Write(string text, Style style)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(text))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            style ??= Style.Plain;
 | 
			
		||||
 | 
			
		||||
            var parts = text.NormalizeLineEndings().Split(new[] { '\n' });
 | 
			
		||||
            foreach (var (_, _, last, part) in parts.Enumerate())
 | 
			
		||||
            {
 | 
			
		||||
                if (!string.IsNullOrEmpty(part))
 | 
			
		||||
                {
 | 
			
		||||
                    _out.Write(AnsiBuilder.GetAnsi(_system, part, Decoration, Foreground, Background));
 | 
			
		||||
                    _out.Write(AnsiBuilder.GetAnsi(Capabilities, part, style.Decoration, style.Foreground, style.Background, style.Link));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!last)
 | 
			
		||||
 
 | 
			
		||||
@@ -56,10 +56,7 @@ namespace Spectre.Console.Internal
 | 
			
		||||
 | 
			
		||||
            if (supportsAnsi)
 | 
			
		||||
            {
 | 
			
		||||
                return new AnsiConsoleRenderer(buffer, colorSystem, legacyConsole)
 | 
			
		||||
                {
 | 
			
		||||
                    Decoration = Decoration.None,
 | 
			
		||||
                };
 | 
			
		||||
                return new AnsiConsoleRenderer(buffer, colorSystem, legacyConsole);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new FallbackConsoleRenderer(buffer, colorSystem, legacyConsole);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,5 +4,7 @@ namespace Spectre.Console.Internal
 | 
			
		||||
    {
 | 
			
		||||
        public const int DefaultBufferWidth = 80;
 | 
			
		||||
        public const int DefaultBufferHeight = 9001;
 | 
			
		||||
 | 
			
		||||
        public const string EmptyLink = "https://emptylink";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,147 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
 | 
			
		||||
namespace Spectre.Console.Internal
 | 
			
		||||
{
 | 
			
		||||
    internal static class AnsiConsoleExtensions
 | 
			
		||||
    {
 | 
			
		||||
        public static IDisposable PushStyle(this IAnsiConsole console, Style style)
 | 
			
		||||
        {
 | 
			
		||||
            if (console is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (style is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(style));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var current = new Style(console.Foreground, console.Background, console.Decoration);
 | 
			
		||||
            console.SetColor(style.Foreground, true);
 | 
			
		||||
            console.SetColor(style.Background, false);
 | 
			
		||||
            console.Decoration = style.Decoration;
 | 
			
		||||
            return new StyleScope(console, current);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static IDisposable PushColor(this IAnsiConsole console, Color color, bool foreground)
 | 
			
		||||
        {
 | 
			
		||||
            if (console is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var current = foreground ? console.Foreground : console.Background;
 | 
			
		||||
            console.SetColor(color, foreground);
 | 
			
		||||
            return new ColorScope(console, current, foreground);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static IDisposable PushDecoration(this IAnsiConsole console, Decoration decoration)
 | 
			
		||||
        {
 | 
			
		||||
            if (console is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var current = console.Decoration;
 | 
			
		||||
            console.Decoration = decoration;
 | 
			
		||||
            return new DecorationScope(console, current);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetColor(this IAnsiConsole console, Color color, bool foreground)
 | 
			
		||||
        {
 | 
			
		||||
            if (console is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (foreground)
 | 
			
		||||
            {
 | 
			
		||||
                console.Foreground = color;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                console.Background = color;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal sealed class StyleScope : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IAnsiConsole _console;
 | 
			
		||||
        private readonly Style _style;
 | 
			
		||||
 | 
			
		||||
        public StyleScope(IAnsiConsole console, Style style)
 | 
			
		||||
        {
 | 
			
		||||
            _console = console ?? throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            _style = style ?? throw new ArgumentNullException(nameof(style));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations")]
 | 
			
		||||
        [SuppressMessage("Performance", "CA1821:Remove empty Finalizers")]
 | 
			
		||||
        ~StyleScope()
 | 
			
		||||
        {
 | 
			
		||||
            throw new InvalidOperationException("Style scope was not disposed.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
            _console.SetColor(_style.Foreground, true);
 | 
			
		||||
            _console.SetColor(_style.Background, false);
 | 
			
		||||
            _console.Decoration = _style.Decoration;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal sealed class ColorScope : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IAnsiConsole _console;
 | 
			
		||||
        private readonly Color _color;
 | 
			
		||||
        private readonly bool _foreground;
 | 
			
		||||
 | 
			
		||||
        public ColorScope(IAnsiConsole console, Color color, bool foreground)
 | 
			
		||||
        {
 | 
			
		||||
            _console = console ?? throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            _color = color;
 | 
			
		||||
            _foreground = foreground;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations")]
 | 
			
		||||
        [SuppressMessage("Performance", "CA1821:Remove empty Finalizers")]
 | 
			
		||||
        ~ColorScope()
 | 
			
		||||
        {
 | 
			
		||||
            throw new InvalidOperationException("Color scope was not disposed.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
            _console.SetColor(_color, _foreground);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal sealed class DecorationScope : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IAnsiConsole _console;
 | 
			
		||||
        private readonly Decoration _decoration;
 | 
			
		||||
 | 
			
		||||
        public DecorationScope(IAnsiConsole console, Decoration decoration)
 | 
			
		||||
        {
 | 
			
		||||
            _console = console ?? throw new ArgumentNullException(nameof(console));
 | 
			
		||||
            _decoration = decoration;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations")]
 | 
			
		||||
        [SuppressMessage("Performance", "CA1821:Remove empty Finalizers")]
 | 
			
		||||
        ~DecorationScope()
 | 
			
		||||
        {
 | 
			
		||||
            throw new InvalidOperationException("Decoration scope was not disposed.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            GC.SuppressFinalize(this);
 | 
			
		||||
            _console.Decoration = _decoration;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -78,5 +78,28 @@ namespace Spectre.Console.Internal
 | 
			
		||||
 | 
			
		||||
            return result.ToArray();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/
 | 
			
		||||
        public static int GetDeterministicHashCode(this string str)
 | 
			
		||||
        {
 | 
			
		||||
            unchecked
 | 
			
		||||
            {
 | 
			
		||||
                var hash1 = (5381 << 16) + 5381;
 | 
			
		||||
                var hash2 = hash1;
 | 
			
		||||
 | 
			
		||||
                for (var i = 0; i < str.Length; i += 2)
 | 
			
		||||
                {
 | 
			
		||||
                    hash1 = ((hash1 << 5) + hash1) ^ str[i];
 | 
			
		||||
                    if (i == str.Length - 1)
 | 
			
		||||
                    {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return hash1 + (hash2 * 1566083941);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
@@ -6,16 +5,11 @@ namespace Spectre.Console.Internal
 | 
			
		||||
{
 | 
			
		||||
    internal sealed class FallbackConsoleRenderer : IAnsiConsole
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ConsoleColor _defaultForeground;
 | 
			
		||||
        private readonly ConsoleColor _defaultBackground;
 | 
			
		||||
 | 
			
		||||
        private readonly TextWriter _out;
 | 
			
		||||
        private readonly ColorSystem _system;
 | 
			
		||||
        private ConsoleColor _foreground;
 | 
			
		||||
        private ConsoleColor _background;
 | 
			
		||||
        private Style? _lastStyle;
 | 
			
		||||
 | 
			
		||||
        public Capabilities Capabilities { get; }
 | 
			
		||||
 | 
			
		||||
        public Encoding Encoding { get; }
 | 
			
		||||
 | 
			
		||||
        public int Width
 | 
			
		||||
@@ -44,47 +38,6 @@ namespace Spectre.Console.Internal
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Decoration Decoration { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Color Foreground
 | 
			
		||||
        {
 | 
			
		||||
            get => _foreground;
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _foreground = Color.ToConsoleColor(value);
 | 
			
		||||
                if (_system != ColorSystem.NoColors && _out.IsStandardOut())
 | 
			
		||||
                {
 | 
			
		||||
                    if ((int)_foreground == -1)
 | 
			
		||||
                    {
 | 
			
		||||
                        _foreground = _defaultForeground;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    System.Console.ForegroundColor = _foreground;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Color Background
 | 
			
		||||
        {
 | 
			
		||||
            get => _background;
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _background = Color.ToConsoleColor(value);
 | 
			
		||||
                if (_system != ColorSystem.NoColors && _out.IsStandardOut())
 | 
			
		||||
                {
 | 
			
		||||
                    if ((int)_background == -1)
 | 
			
		||||
                    {
 | 
			
		||||
                        _background = _defaultBackground;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (_system != ColorSystem.NoColors)
 | 
			
		||||
                    {
 | 
			
		||||
                        System.Console.BackgroundColor = _background;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public FallbackConsoleRenderer(TextWriter @out, ColorSystem system, bool legacyConsole)
 | 
			
		||||
        {
 | 
			
		||||
            _out = @out;
 | 
			
		||||
@@ -92,25 +45,46 @@ namespace Spectre.Console.Internal
 | 
			
		||||
 | 
			
		||||
            if (_out.IsStandardOut())
 | 
			
		||||
            {
 | 
			
		||||
                _defaultForeground = System.Console.ForegroundColor;
 | 
			
		||||
                _defaultBackground = System.Console.BackgroundColor;
 | 
			
		||||
 | 
			
		||||
                Encoding = System.Console.OutputEncoding;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                _defaultForeground = ConsoleColor.Gray;
 | 
			
		||||
                _defaultBackground = ConsoleColor.Black;
 | 
			
		||||
 | 
			
		||||
                Encoding = Encoding.UTF8;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Capabilities = new Capabilities(false, _system, legacyConsole);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Write(string text)
 | 
			
		||||
        public void Write(string text, Style style)
 | 
			
		||||
        {
 | 
			
		||||
            if (_lastStyle?.Equals(style) != true)
 | 
			
		||||
            {
 | 
			
		||||
                SetStyle(style);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _out.Write(text.NormalizeLineEndings(native: true));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void SetStyle(Style style)
 | 
			
		||||
        {
 | 
			
		||||
            _lastStyle = style;
 | 
			
		||||
 | 
			
		||||
            if (_out.IsStandardOut())
 | 
			
		||||
            {
 | 
			
		||||
                System.Console.ResetColor();
 | 
			
		||||
 | 
			
		||||
                var background = Color.ToConsoleColor(style.Background);
 | 
			
		||||
                if (_system != ColorSystem.NoColors && _out.IsStandardOut() && (int)background != -1)
 | 
			
		||||
                {
 | 
			
		||||
                    System.Console.BackgroundColor = background;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var foreground = Color.ToConsoleColor(style.Foreground);
 | 
			
		||||
                if (_system != ColorSystem.NoColors && _out.IsStandardOut() && (int)foreground != -1)
 | 
			
		||||
                {
 | 
			
		||||
                    System.Console.ForegroundColor = foreground;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@ namespace Spectre.Console.Internal
 | 
			
		||||
            var effectiveDecoration = (Decoration?)null;
 | 
			
		||||
            var effectiveForeground = (Color?)null;
 | 
			
		||||
            var effectiveBackground = (Color?)null;
 | 
			
		||||
            var effectiveLink = (string?)null;
 | 
			
		||||
 | 
			
		||||
            var parts = text.Split(new[] { ' ' });
 | 
			
		||||
            var foreground = true;
 | 
			
		||||
@@ -51,6 +52,23 @@ namespace Spectre.Console.Internal
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (part.StartsWith("link=", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                {
 | 
			
		||||
                    if (effectiveLink != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        error = "A link has already been set.";
 | 
			
		||||
                        return null;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    effectiveLink = part.Substring(5);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                else if (part.StartsWith("link", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
                {
 | 
			
		||||
                    effectiveLink = Constants.EmptyLink;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var decoration = DecorationTable.GetDecoration(part);
 | 
			
		||||
                if (decoration != null)
 | 
			
		||||
                {
 | 
			
		||||
@@ -116,7 +134,11 @@ namespace Spectre.Console.Internal
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            error = null;
 | 
			
		||||
            return new Style(effectiveForeground, effectiveBackground, effectiveDecoration);
 | 
			
		||||
            return new Style(
 | 
			
		||||
                effectiveForeground,
 | 
			
		||||
                effectiveBackground,
 | 
			
		||||
                effectiveDecoration,
 | 
			
		||||
                effectiveLink);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:Do not catch general exception types")]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user