Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/Spectre.Console.Ansi.Tests/AnsiMarkupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ public void Should_Escape_Markup_Blocks_As_Expected()
}

[Theory]
[InlineData("[yellow]Hello[/]", "Hello")]
[InlineData("[yellow]Hello [italic]World[/]![/]", "Hello World!")]
[InlineData("[yellow]Hello[/]", "\e[93mHello\e[0m")]
[InlineData("[yellow]Hello [italic]World[/]![/]", "\e[93mHello \e[0m\e[3;93mWorld\e[0m\e[93m!\e[0m")]
public void Should_Output_Expected_Ansi_For_Markup(string text, string expected)
{
// Given
Expand All @@ -265,7 +265,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Url_And_Text()

// Then
fixture.Output.ShouldMatch(
"]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\Click to visit my blog]8;;\\\\");
"\e]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\e\\\\Click to visit my blog\e]8;;\e\\\\");
}

[Fact]
Expand All @@ -279,7 +279,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Only_Url()

// Then
fixture.Output.ShouldMatch(
"]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\https:\\/\\/patriksvensson\\.se]8;;\\\\");
"\e]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\e\\\\https:\\/\\/patriksvensson\\.se\e]8;;\e\\\\");
}

[Fact]
Expand All @@ -294,7 +294,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Bracket_In_Url_Only()

// Then
fixture.Output.ShouldMatch(
"]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt]8;;\\\\");
"\e]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\e\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt\e]8;;\e\\\\");
}

[Fact]
Expand All @@ -310,7 +310,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Bracket_In_Url()

// Then
fixture.Output.ShouldMatch(
"]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt]8;;\\\\");
"\e]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\e\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt\e]8;;\e\\\\");
}

[Theory]
Expand Down
33 changes: 32 additions & 1 deletion src/Spectre.Console.Ansi/Link.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Spectre.Console;
/// Represents a link.
/// </summary>
/// <param name="url">The link URL.</param>
public sealed class Link(string url)
public sealed class Link(string url) : IEquatable<Link>
{
/// <summary>
/// Gets the link ID.
Expand All @@ -15,4 +15,35 @@ public sealed class Link(string url)
/// Gets the url.
/// </summary>
public string Url { get; } = url;

/// <inheritdoc />
public bool Equals(Link? other)
{
if (other is null)
{
return false;
}

if (ReferenceEquals(this, other))
{
return true;
}

return Id == other.Id && Url == other.Url;
}

/// <inheritdoc />
public override bool Equals(object? obj)
{
return ReferenceEquals(this, obj) || obj is Link other && Equals(other);
}

/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (Id.GetHashCode() * 397) ^ Url.GetHashCode();
}
}
}
8 changes: 4 additions & 4 deletions src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Ansi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ public void Should_Write_Ansi_Codes_To_Console_If_Supported()
.EmitAnsiSequences();

// When
console.WriteAnsi("Hello");
console.WriteAnsi("\e[101mHello\e[0m");

// Then
console.Output.NormalizeLineEndings()
.ShouldBe("Hello");
.ShouldBe("\e[101mHello\e[0m");
}

[Fact]
Expand All @@ -31,7 +31,7 @@ public void Should_Not_Write_Ansi_Codes_To_Console_If_Not_Supported()
.EmitAnsiSequences();

// When
console.WriteAnsi("Hello");
console.WriteAnsi("\e[101mHello\e[0m");

// Then
console.Output.NormalizeLineEndings()
Expand All @@ -49,7 +49,7 @@ public void Should_Return_Ansi_For_Renderable()
var result = console.ToAnsi(markup);

// Then
result.ShouldBe("Hello World!");
result.ShouldBe("\e[38;5;11mHello \e[0m\e[38;5;12mWorld\e[0m\e[38;5;11m!\e[0m");
}
}
}
10 changes: 5 additions & 5 deletions src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Cursor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ public sealed class Cursor
public sealed class TheMoveMethod
{
[Theory]
[InlineData(CursorDirection.Up, "HelloWorld")]
[InlineData(CursorDirection.Down, "HelloWorld")]
[InlineData(CursorDirection.Right, "HelloWorld")]
[InlineData(CursorDirection.Left, "HelloWorld")]
[InlineData(CursorDirection.Up, "Hello\e[2AWorld")]
[InlineData(CursorDirection.Down, "Hello\e[2BWorld")]
[InlineData(CursorDirection.Right, "Hello\e[2CWorld")]
[InlineData(CursorDirection.Left, "Hello\e[2DWorld")]
public void Should_Return_Correct_Ansi_Code(CursorDirection direction, string expected)
{
// Given
Expand Down Expand Up @@ -40,7 +40,7 @@ public void Should_Return_Correct_Ansi_Code()
console.Write("World");

// Then
console.Output.ShouldBe("HelloWorld");
console.Output.ShouldBe("Hello\e[3;5HWorld");
}
}
}
Expand Down
59 changes: 52 additions & 7 deletions src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ public partial class AnsiConsoleTests
public sealed class Markup
{
[Theory]
[InlineData("[yellow]Hello[/]", "Hello")]
[InlineData("[yellow]Hello [italic]World[/]![/]", "Hello World!")]
[InlineData("[yellow]Hello[/]", "\e[93mHello\e[0m")]
[InlineData("[yellow]Hello [italic]World[/]![/]", "\e[93mHello \e[0m\e[3;93mWorld\e[0m\e[93m!\e[0m")]
public void Should_Output_Expected_Ansi_For_Markup(string markup, string expected)
{
// Given
Expand All @@ -32,7 +32,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Url_And_Text()
console.Markup("[link=https://patriksvensson.se]Click to visit my blog[/]");

// Then
console.Output.ShouldMatch("]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\Click to visit my blog]8;;\\\\");
console.Output.ShouldMatch("\e]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\e\\\\Click to visit my blog\e]8;;\e\\\\");
}

[Fact]
Expand All @@ -46,7 +46,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Only_Url()
console.Markup("[link]https://patriksvensson.se[/]");

// Then
console.Output.ShouldMatch("]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\\\\https:\\/\\/patriksvensson\\.se]8;;\\\\");
console.Output.ShouldMatch("\e]8;id=[0-9]*;https:\\/\\/patriksvensson\\.se\e\\\\https:\\/\\/patriksvensson\\.se\e]8;;\e\\\\");
}

[Fact]
Expand All @@ -61,7 +61,7 @@ public void Should_Output_Expected_Ansi_For_Link_With_Bracket_In_Url_Only()
console.Markup($"[link]{Path.EscapeMarkup()}[/]");

// Then
console.Output.ShouldMatch("]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt]8;;\\\\");
console.Output.ShouldMatch("\e]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\e\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt\e]8;;\e\\\\");
}

[Fact]
Expand All @@ -76,11 +76,11 @@ public void Should_Output_Expected_Ansi_For_Link_With_Bracket_In_Url()
console.Markup($"[link={Path.EscapeMarkup()}]{Path.EscapeMarkup()}[/]");

// Then
console.Output.ShouldMatch("]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt]8;;\\\\");
console.Output.ShouldMatch("\e]8;id=[0-9]*;file:\\/\\/c:\\/temp\\/\\[x\\].txt\e\\\\file:\\/\\/c:\\/temp\\/\\[x\\].txt\e]8;;\e\\\\");
}

[Theory]
[InlineData("[yellow]Hello [[ World[/]", "Hello [ World")]
[InlineData("[yellow]Hello [[ World[/]", "\e[93mHello [ World\e[0m")]
public void Should_Be_Able_To_Escape_Tags(string markup, string expected)
{
// Given
Expand Down Expand Up @@ -174,5 +174,50 @@ public void Should_Not_Fail_As_In_GH1024(string markup, string expected)
// Then
console.Output.ShouldBe(expected);
}

[Fact]
[GitHubIssue("https://github.com/spectreconsole/spectre.console/issues/2083")]
[GitHubIssue("https://github.com/spectreconsole/spectre.console/issues/2078")]
public void Should_Preserve_Links_When_Multiple_Segments_Are_Merged()
{
// Given
var console = new TestConsole()
.Width(8)
.SupportsAnsi(true)
.EmitAnsiSequences();

// When
console.Write(
Align.Center(
new Spectre.Console.Markup(
"[link=https://example.com/readme.md]Docs[/]")));

// Then
console.Output.ShouldMatch(
" \e]8;id=[0-9]*;https:\\/\\/example\\.com\\/readme.md\e\\\\Docs\e]8;;\e\\\\ ");
}

[Fact]
[GitHubIssue("https://github.com/spectreconsole/spectre.console/issues/2083")]
[GitHubIssue("https://github.com/spectreconsole/spectre.console/issues/2078")]
public void Should_Preserve_Links_Over_Line_Breaks_When_Multiple_Segments_Are_Merged()
{
// Given
var console = new TestConsole()
.Width(8)
.SupportsAnsi(true)
.EmitAnsiSequences();

// When
console.Write(
Align.Center(
new Spectre.Console.Markup(
"[link=https://example.com/readme.md]Foo and Bar[/]")));

// Then
console.Output.ShouldMatch(
"\e]8;id=[0-9]*;https:\\/\\/example\\.com\\/readme.md\e\\\\Foo and \e]8;;\e\\\\\n" +
" \e]8;id=[0-9]*;https:\\/\\/example\\.com\\/readme.md\e\\\\Bar\e]8;;\e\\\\ ");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void Should_Print_Simple_Interpolated_Strings()
console.MarkupInterpolated($"[Green]{Path}[/]");

// Then
console.Output.ShouldBe($"{Path}");
console.Output.ShouldBe($"\e[32m{Path}\e[0m");
}

[Fact]
Expand All @@ -34,7 +34,7 @@ public void Should_Not_Throw_Error_On_Links_Brackets()

// Then
var pathAsRegEx = Regex.Replace(Path, "([/\\[\\]\\\\])", "\\$1", RegexOptions.Compiled | RegexOptions.IgnoreCase);
console.Output.ShouldMatch($"\\]8;id=[0-9]+;{pathAsRegEx}\\\\{pathAsRegEx}\\]8;;\\\\");
console.Output.ShouldMatch($"\e\\]8;id=[0-9]+;{pathAsRegEx}\e\\\\{pathAsRegEx}\e\\]8;;\e\\\\");
}
}
}
22 changes: 11 additions & 11 deletions src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ namespace Spectre.Console.Tests.Unit;
public partial class AnsiConsoleTests
{
[Theory]
[InlineData(Decoration.Bold, "\u001b[1mHello World")]
[InlineData(Decoration.Dim, "\u001b[2mHello World")]
[InlineData(Decoration.Italic, "\u001b[3mHello World")]
[InlineData(Decoration.Underline, "\u001b[4mHello World")]
[InlineData(Decoration.Invert, "\u001b[7mHello World")]
[InlineData(Decoration.Conceal, "\u001b[8mHello World")]
[InlineData(Decoration.SlowBlink, "\u001b[5mHello World")]
[InlineData(Decoration.RapidBlink, "\u001b[6mHello World")]
[InlineData(Decoration.Strikethrough, "\u001b[9mHello World")]
[InlineData(Decoration.Bold, "\u001b[1mHello World\e[0m")]
[InlineData(Decoration.Dim, "\u001b[2mHello World\e[0m")]
[InlineData(Decoration.Italic, "\u001b[3mHello World\e[0m")]
[InlineData(Decoration.Underline, "\u001b[4mHello World\e[0m")]
[InlineData(Decoration.Invert, "\u001b[7mHello World\e[0m")]
[InlineData(Decoration.Conceal, "\u001b[8mHello World\e[0m")]
[InlineData(Decoration.SlowBlink, "\u001b[5mHello World\e[0m")]
[InlineData(Decoration.RapidBlink, "\u001b[6mHello World\e[0m")]
[InlineData(Decoration.Strikethrough, "\u001b[9mHello World\e[0m")]
public void Should_Write_Decorated_Text_Correctly(Decoration decoration, string expected)
{
// Given
Expand All @@ -26,8 +26,8 @@ public void Should_Write_Decorated_Text_Correctly(Decoration decoration, string
}

[Theory]
[InlineData(Decoration.Bold | Decoration.Underline, "\u001b[1;4mHello World")]
[InlineData(Decoration.Bold | Decoration.Underline | Decoration.Conceal, "\u001b[1;4;8mHello World")]
[InlineData(Decoration.Bold | Decoration.Underline, "\u001b[1;4mHello World\e[0m")]
[InlineData(Decoration.Bold | Decoration.Underline | Decoration.Conceal, "\u001b[1;4;8mHello World\e[0m")]
public void Should_Write_Text_With_Multiple_Decorations_Correctly(Decoration decoration, string expected)
{
// Given
Expand Down
8 changes: 4 additions & 4 deletions src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ public partial class AnsiConsoleTests
public sealed class Clear
{
[Theory]
[InlineData(false, "HelloWorld")]
[InlineData(true, "HelloWorld")]
[InlineData(false, "Hello\e[2J\e[3JWorld")]
[InlineData(true, "Hello\e[2J\e[3J\e[1;1HWorld")]
public void Should_Clear_Screen(bool home, string expected)
{
// Given
Expand Down Expand Up @@ -123,7 +123,7 @@ public void Should_Reset_Colors_Correctly_After_Line_Break()

// Then
console.Output.NormalizeLineEndings()
.ShouldBe("Hello\nWorld\n");
.ShouldBe("\e[101mHello\e[0m\n\e[102mWorld\e[0m\n");
}

[Fact]
Expand All @@ -139,7 +139,7 @@ public void Should_Reset_Colors_Correctly_After_Line_Break_In_Text()

// Then
console.Output.NormalizeLineEndings()
.ShouldBe("Hello\nWorld\n");
.ShouldBe("\e[101mHello\e[0m\n\e[101mWorld\e[0m\n");
}
}

Expand Down
Loading