mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-16 00:42:51 +08:00
Update emoji support
* Add constants for emojis * Move emoji shortcode rendering to Markup * Add documentation * Add example * Add tests
This commit is contained in:
parent
090b30f731
commit
eeb3f967b6
1
.github/workflows/ci.yaml
vendored
1
.github/workflows/ci.yaml
vendored
@ -69,6 +69,7 @@ jobs:
|
|||||||
dotnet example grid
|
dotnet example grid
|
||||||
dotnet example panel
|
dotnet example panel
|
||||||
dotnet example colors
|
dotnet example colors
|
||||||
|
dotnet example emojis
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -22,11 +22,23 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="src\Data\emojis.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="src\Data\emojis.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" />
|
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" />
|
||||||
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" />
|
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="input\assets\images\emojis\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="Versioning" BeforeTargets="MinVer">
|
<Target Name="Versioning" BeforeTargets="MinVer">
|
||||||
<PropertyGroup Label="Build">
|
<PropertyGroup Label="Build">
|
||||||
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
|
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
|
||||||
|
@ -19,6 +19,7 @@ namespace Docs
|
|||||||
.ConfigureDeployment(deployBranch: "docs")
|
.ConfigureDeployment(deployBranch: "docs")
|
||||||
.AddShortcode("Children", typeof(ChildrenShortcode))
|
.AddShortcode("Children", typeof(ChildrenShortcode))
|
||||||
.AddShortcode("ColorTable", typeof(ColorTableShortcode))
|
.AddShortcode("ColorTable", typeof(ColorTableShortcode))
|
||||||
|
.AddShortcode("EmojiTable", typeof(EmojiTableShortcode))
|
||||||
.AddPipelines()
|
.AddPipelines()
|
||||||
.RunAsync();
|
.RunAsync();
|
||||||
|
|
||||||
|
@ -128,14 +128,28 @@
|
|||||||
{
|
{
|
||||||
IDocument root = OutputPages["index.html"].First();
|
IDocument root = OutputPages["index.html"].First();
|
||||||
<div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)">
|
<div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)">
|
||||||
@Html.DocumentLink(root)
|
@if(root.ShowLink())
|
||||||
|
{
|
||||||
|
@Html.DocumentLink(root)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@root.GetTitle()
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
|
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
|
||||||
{
|
{
|
||||||
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
|
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
|
||||||
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
|
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
|
||||||
@Html.DocumentLink(document)
|
@if(document.ShowLink())
|
||||||
|
{
|
||||||
|
@Html.DocumentLink(document)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@document.GetTitle()
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (documentChildren.OnlyVisible().Any())
|
@if (documentChildren.OnlyVisible().Any())
|
||||||
|
38
docs/input/appendix/emojis.md
Normal file
38
docs/input/appendix/emojis.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
Title: Emojis
|
||||||
|
Order: 3
|
||||||
|
---
|
||||||
|
|
||||||
|
Please note that what emojis that can be used is completely up to
|
||||||
|
the operating system and/or terminal you're using, and no guarantees
|
||||||
|
can be made of how it will look. Calculating the width of emojis
|
||||||
|
is also not an exact science in many ways, so milage might vary when
|
||||||
|
used in tables, panels or grids.
|
||||||
|
|
||||||
|
To ensure best compatibility, consider only using emojis introduced
|
||||||
|
before Unicode 13.0 that belongs in the `Emoji_Presentation` category
|
||||||
|
in the official emoji list at
|
||||||
|
https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Markup
|
||||||
|
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||||
|
|
||||||
|
// Constant
|
||||||
|
var hello = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica;
|
||||||
|
```
|
||||||
|
|
||||||
|
# Replacing emojis in text
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var phrase = "Mmmm :birthday_cake:";
|
||||||
|
var rendered = Emoji.Replace(phrase);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Emojis
|
||||||
|
|
||||||
|
_The images in the table below might not render correctly in your
|
||||||
|
browser for the same reasons mentioned in the `Compatibility` section._
|
||||||
|
|
||||||
|
<?# EmojiTable /?>
|
@ -1,3 +1,10 @@
|
|||||||
Title: Appendix
|
Title: Appendix
|
||||||
Order: 10
|
Order: 10
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# Sections
|
||||||
|
|
||||||
|
* [Styles](xref:styles)
|
||||||
|
* [Colors](xref:colors)
|
||||||
|
* [Borders](xref:borders)
|
||||||
|
* [Emojis](xref:emojis)
|
@ -2,8 +2,7 @@ Title: Markup
|
|||||||
Order: 2
|
Order: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
In `Spectre.Console` there's a class called `Markup` that
|
The class `Markup` allows you to output rich text to the console.
|
||||||
allows you to output rich text to the console.
|
|
||||||
|
|
||||||
# Syntax
|
# Syntax
|
||||||
|
|
||||||
@ -54,6 +53,16 @@ You can set the background color in markup by prefixing the color with
|
|||||||
[default on blue]World[/]
|
[default on blue]World[/]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Rendering emojis
|
||||||
|
|
||||||
|
To output an emoji as part of markup, you can use emoji shortcodes.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||||
|
```
|
||||||
|
|
||||||
|
For a list of emoji, see the [Emojis](xref:styles) appendix section.
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
|
|
||||||
For a list of colors, see the [Colors](xref:colors) appendix section.
|
For a list of colors, see the [Colors](xref:colors) appendix section.
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
namespace Docs
|
namespace Docs
|
||||||
{
|
{
|
||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
public const string NoContainer = nameof(NoContainer);
|
public const string NoContainer = nameof(NoContainer);
|
||||||
public const string NoSidebar = nameof(NoSidebar);
|
public const string NoSidebar = nameof(NoSidebar);
|
||||||
|
public const string NoLink = nameof(NoLink);
|
||||||
public const string Topic = nameof(Topic);
|
public const string Topic = nameof(Topic);
|
||||||
public const string EditLink = nameof(EditLink);
|
public const string EditLink = nameof(EditLink);
|
||||||
public const string Description = nameof(Description);
|
public const string Description = nameof(Description);
|
||||||
public const string Hidden = nameof(Hidden);
|
public const string Hidden = nameof(Hidden);
|
||||||
|
|
||||||
|
public static class Emojis
|
||||||
|
{
|
||||||
|
public const string Root = "EMOJIS_ROOT";
|
||||||
|
}
|
||||||
|
|
||||||
public static class Colors
|
public static class Colors
|
||||||
{
|
{
|
||||||
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
|
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
|
||||||
|
7946
docs/src/Data/emojis.json
Normal file
7946
docs/src/Data/emojis.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
using Statiq.Common;
|
using Statiq.Common;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@ -16,6 +16,11 @@ namespace Docs
|
|||||||
return !document.GetBool(Constants.Hidden, false);
|
return !document.GetBool(Constants.Hidden, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ShowLink(this IDocument document)
|
||||||
|
{
|
||||||
|
return !document.GetBool(Constants.NoLink, false);
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<IDocument> OnlyVisible(this IEnumerable<IDocument> source)
|
public static IEnumerable<IDocument> OnlyVisible(this IEnumerable<IDocument> source)
|
||||||
{
|
{
|
||||||
return source.Where(x => x.IsVisible());
|
return source.Where(x => x.IsVisible());
|
||||||
|
20
docs/src/Models/Emoji.cs
Normal file
20
docs/src/Models/Emoji.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Docs.Models
|
||||||
|
{
|
||||||
|
public sealed class Emoji
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
|
||||||
|
public static List<Emoji> Parse(string json)
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<List<Emoji>>(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
docs/src/Modules/ReadEmbedded.cs
Normal file
41
docs/src/Modules/ReadEmbedded.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Statiq.Common;
|
||||||
|
|
||||||
|
namespace Docs.Modules
|
||||||
|
{
|
||||||
|
public sealed class ReadEmbedded : Module
|
||||||
|
{
|
||||||
|
private readonly System.Reflection.Assembly _assembly;
|
||||||
|
private readonly string _resource;
|
||||||
|
|
||||||
|
public ReadEmbedded(System.Reflection.Assembly assembly, string resource)
|
||||||
|
{
|
||||||
|
_assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
|
||||||
|
_resource = resource ?? throw new ArgumentNullException(nameof(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<IEnumerable<IDocument>> ExecuteContextAsync(IExecutionContext context)
|
||||||
|
{
|
||||||
|
return Task.FromResult((IEnumerable<IDocument>)new[]
|
||||||
|
{
|
||||||
|
context.CreateDocument(ReadResource()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream ReadResource()
|
||||||
|
{
|
||||||
|
var resourceName = _resource.Replace("/", ".");
|
||||||
|
|
||||||
|
var stream = _assembly.GetManifestResourceStream(resourceName);
|
||||||
|
if (stream == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Could not load manifest resource stream.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,13 +26,8 @@ namespace Docs.Pipelines
|
|||||||
new ExecuteConfig(
|
new ExecuteConfig(
|
||||||
Config.FromDocument(async (doc, ctx) =>
|
Config.FromDocument(async (doc, ctx) =>
|
||||||
{
|
{
|
||||||
var colors = Color.Parse(await doc.GetContentStringAsync()).ToList();
|
var data = Color.Parse(await doc.GetContentStringAsync()).ToList();
|
||||||
var definitions = new List<IDocument> { colors.ToDocument(Constants.Colors.Root) };
|
return data.ToDocument(Constants.Colors.Root);
|
||||||
|
|
||||||
return doc.Clone(new MetadataDictionary
|
|
||||||
{
|
|
||||||
[Constants.Colors.Root] = definitions
|
|
||||||
});
|
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
34
docs/src/Pipelines/EmojiPipeline.cs
Normal file
34
docs/src/Pipelines/EmojiPipeline.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Docs.Models;
|
||||||
|
using Docs.Modules;
|
||||||
|
using Statiq.Common;
|
||||||
|
using Statiq.Core;
|
||||||
|
|
||||||
|
namespace Docs.Pipelines
|
||||||
|
{
|
||||||
|
public class EmojiPipeline : Pipeline
|
||||||
|
{
|
||||||
|
public EmojiPipeline()
|
||||||
|
{
|
||||||
|
InputModules = new ModuleList
|
||||||
|
{
|
||||||
|
new ExecuteConfig(
|
||||||
|
Config.FromContext(ctx => {
|
||||||
|
return new ReadEmbedded(
|
||||||
|
typeof(EmojiPipeline).Assembly,
|
||||||
|
"Docs/src/Data/emojis.json");
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
ProcessModules = new ModuleList
|
||||||
|
{
|
||||||
|
new ExecuteConfig(
|
||||||
|
Config.FromDocument(async (doc, ctx) =>
|
||||||
|
{
|
||||||
|
var data = Emoji.Parse(await doc.GetContentStringAsync());
|
||||||
|
return data.ToDocument(Constants.Emojis.Root);
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,11 +17,10 @@ namespace Docs.Shortcodes
|
|||||||
// Get the definition.
|
// Get the definition.
|
||||||
var colors = context.Outputs
|
var colors = context.Outputs
|
||||||
.FromPipeline(nameof(ColorsPipeline))
|
.FromPipeline(nameof(ColorsPipeline))
|
||||||
.First()
|
|
||||||
.GetChildren(Constants.Colors.Root)
|
|
||||||
.OfType<ObjectDocument<List<Color>>>()
|
.OfType<ObjectDocument<List<Color>>>()
|
||||||
.First().Object;
|
.First().Object;
|
||||||
|
|
||||||
|
// Headers
|
||||||
var table = new XElement("table", new XAttribute("class", "table"));
|
var table = new XElement("table", new XAttribute("class", "table"));
|
||||||
var header = new XElement("tr", new XAttribute("class", "color-row"));
|
var header = new XElement("tr", new XAttribute("class", "color-row"));
|
||||||
header.Add(new XElement("th", ""));
|
header.Add(new XElement("th", ""));
|
||||||
|
45
docs/src/Shortcodes/EmojiTableShortcode.cs
Normal file
45
docs/src/Shortcodes/EmojiTableShortcode.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Statiq.Common;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Docs.Pipelines;
|
||||||
|
using Docs.Models;
|
||||||
|
|
||||||
|
namespace Docs.Shortcodes
|
||||||
|
{
|
||||||
|
public class EmojiTableShortcode : SyncShortcode
|
||||||
|
{
|
||||||
|
public override ShortcodeResult Execute(KeyValuePair<string, string>[] args, string content, IDocument document, IExecutionContext context)
|
||||||
|
{
|
||||||
|
var emojis = context.Outputs
|
||||||
|
.FromPipeline(nameof(EmojiPipeline))
|
||||||
|
.OfType<ObjectDocument<List<Emoji>>>()
|
||||||
|
.First().Object;
|
||||||
|
|
||||||
|
// Headers
|
||||||
|
var table = new XElement("table", new XAttribute("class", "table"));
|
||||||
|
var header = new XElement("tr", new XAttribute("class", "emoji-row"));
|
||||||
|
header.Add(new XElement("th", ""));
|
||||||
|
header.Add(new XElement("th", "Markup"));
|
||||||
|
header.Add(new XElement("th", "Constant"));
|
||||||
|
table.Add(header);
|
||||||
|
|
||||||
|
foreach (var emoji in emojis)
|
||||||
|
{
|
||||||
|
var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+");
|
||||||
|
var icon = string.Format("&#x{0};", emoji.Code.Replace("U+", string.Empty));
|
||||||
|
|
||||||
|
var row = new XElement("tr");
|
||||||
|
row.Add(new XElement("td", icon));
|
||||||
|
row.Add(new XElement("td", new XElement("code", $":{emoji.Id}:")));
|
||||||
|
row.Add(new XElement("td", new XElement("code", emoji.Name)));
|
||||||
|
|
||||||
|
table.Add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return table.ToString()
|
||||||
|
.Replace("&#x", "&#x");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
examples/Emojis/Emojis.csproj
Normal file
14
examples/Emojis/Emojis.csproj
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<Description>Demonstrates how to render emojis.</Description>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
17
examples/Emojis/Program.cs
Normal file
17
examples/Emojis/Program.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Emojis
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Markup
|
||||||
|
AnsiConsole.Render(
|
||||||
|
new Panel("[yellow]Hello :globe_showing_europe_africa:![/]")
|
||||||
|
.RoundedBorder()
|
||||||
|
.SetHeader("Markup"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,8 @@ namespace Info
|
|||||||
.AddRow("[b]:artist_palette: Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
|
.AddRow("[b]:artist_palette: Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
|
||||||
.AddRow("[b]:nail_polish: Supports ansi?[/]", $"{GetEmoji(AnsiConsole.Capabilities.SupportsAnsi)}")
|
.AddRow("[b]:nail_polish: Supports ansi?[/]", $"{GetEmoji(AnsiConsole.Capabilities.SupportsAnsi)}")
|
||||||
.AddRow("[b]:top_hat: Legacy console?[/]", $"{GetEmoji(AnsiConsole.Capabilities.LegacyConsole)}")
|
.AddRow("[b]:top_hat: Legacy console?[/]", $"{GetEmoji(AnsiConsole.Capabilities.LegacyConsole)}")
|
||||||
.AddRow("[b]:left-right_arrow: Buffer width[/]", $"{AnsiConsole.Console.Width}")
|
.AddRow("[b]:left_right_arrow: Buffer width[/]", $"{AnsiConsole.Console.Width}")
|
||||||
.AddRow("[b]:up-down_arrow: Buffer height[/]", $"{AnsiConsole.Console.Height}");
|
.AddRow("[b]:up_down_arrow: Buffer height[/]", $"{AnsiConsole.Console.Height}");
|
||||||
|
|
||||||
AnsiConsole.Render(
|
AnsiConsole.Render(
|
||||||
new Panel(grid)
|
new Panel(grid)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
$Output = Join-Path $PSScriptRoot "Temp"
|
$Output = Join-Path $PSScriptRoot "Temp"
|
||||||
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
||||||
|
$Docs = Join-Path $PSScriptRoot "/../../docs/src/Data"
|
||||||
|
|
||||||
if(!(Test-Path $Output -PathType Container)) {
|
if(!(Test-Path $Output -PathType Container)) {
|
||||||
New-Item -ItemType Directory -Path $Output | Out-Null
|
New-Item -ItemType Directory -Path $Output | Out-Null
|
||||||
@ -11,7 +12,7 @@ if(!(Test-Path $Output -PathType Container)) {
|
|||||||
|
|
||||||
# Generate the files
|
# Generate the files
|
||||||
Push-Location Generator
|
Push-Location Generator
|
||||||
&dotnet run -- emoji "$Output"
|
&dotnet run -- emoji "$Output" --input $Output
|
||||||
if(!$?) {
|
if(!$?) {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
Throw "An error occured when generating code."
|
Throw "An error occured when generating code."
|
||||||
@ -19,4 +20,5 @@ if(!$?) {
|
|||||||
Pop-Location
|
Pop-Location
|
||||||
|
|
||||||
# Copy the files to the correct location
|
# Copy the files to the correct location
|
||||||
Copy-Item (Join-Path "$Output" "Emoji.Generated.cs") -Destination "$Source/Emoji.Generated.cs"
|
Copy-Item (Join-Path "$Output" "Emoji.Generated.cs") -Destination "$Source/Emoji.Generated.cs"
|
||||||
|
Copy-Item (Join-Path "$Output" "emojis.json") -Destination "$Docs/emojis.json"
|
@ -55,5 +55,8 @@ namespace Generator.Commands
|
|||||||
{
|
{
|
||||||
[CommandArgument(0, "<OUTPUT>")]
|
[CommandArgument(0, "<OUTPUT>")]
|
||||||
public string Output { get; set; }
|
public string Output { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-i|--input <PATH>")]
|
||||||
|
public string Input { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -10,52 +11,72 @@ using Scriban.Runtime;
|
|||||||
using Spectre.Cli;
|
using Spectre.Cli;
|
||||||
using Spectre.IO;
|
using Spectre.IO;
|
||||||
using Path = Spectre.IO.Path;
|
using Path = Spectre.IO.Path;
|
||||||
|
using SpectreEnvironment = Spectre.IO.Environment;
|
||||||
|
|
||||||
namespace Generator.Commands
|
namespace Generator.Commands
|
||||||
{
|
{
|
||||||
public sealed class EmojiGeneratorCommand : AsyncCommand<GeneratorCommandSettings>
|
public sealed class EmojiGeneratorCommand : AsyncCommand<GeneratorCommandSettings>
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly IEnvironment _environment;
|
||||||
private readonly IHtmlParser _parser;
|
private readonly IHtmlParser _parser;
|
||||||
|
|
||||||
|
private readonly Dictionary<string, string> _templates = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "Templates/Emoji.Generated.template", "Emoji.Generated.cs" },
|
||||||
|
{ "Templates/Emoji.Json.template", "emojis.json" },
|
||||||
|
};
|
||||||
|
|
||||||
public EmojiGeneratorCommand()
|
public EmojiGeneratorCommand()
|
||||||
{
|
{
|
||||||
_fileSystem = new FileSystem();
|
_fileSystem = new FileSystem();
|
||||||
|
_environment = new SpectreEnvironment();
|
||||||
_parser = new HtmlParser();
|
_parser = new HtmlParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<int> ExecuteAsync(CommandContext context, GeneratorCommandSettings settings)
|
public override async Task<int> ExecuteAsync(CommandContext context, GeneratorCommandSettings settings)
|
||||||
{
|
{
|
||||||
var output = new DirectoryPath(settings.Output);
|
var output = new DirectoryPath(settings.Output);
|
||||||
|
|
||||||
if (!_fileSystem.Directory.Exists(settings.Output))
|
if (!_fileSystem.Directory.Exists(settings.Output))
|
||||||
{
|
{
|
||||||
_fileSystem.Directory.Create(settings.Output);
|
_fileSystem.Directory.Create(settings.Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
var templatePath = new FilePath("Templates/Emoji.Generated.template");
|
var stream = await FetchEmojis(settings);
|
||||||
|
var document = await _parser.ParseDocumentAsync(stream);
|
||||||
|
var emojis = Emoji.Parse(document).OrderBy(x => x.Name)
|
||||||
|
.Where(emoji => !emoji.HasCombinators)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var emojis = await FetchEmojis("http://www.unicode.org/emoji/charts/emoji-list.html");
|
// Render all templates
|
||||||
|
foreach (var (templateFilename, outputFilename) in _templates)
|
||||||
|
{
|
||||||
|
var result = await RenderTemplate(new FilePath(templateFilename), emojis);
|
||||||
|
|
||||||
var result = await RenderTemplate(templatePath, emojis);
|
var outputPath = output.CombineWithFilePath(outputFilename);
|
||||||
|
await File.WriteAllTextAsync(outputPath.FullPath, result);
|
||||||
var outputPath = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs"));
|
}
|
||||||
|
|
||||||
await File.WriteAllTextAsync(outputPath.FullPath, result);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IReadOnlyCollection<Emoji>> FetchEmojis(string url)
|
private async Task<Stream> FetchEmojis(GeneratorCommandSettings settings)
|
||||||
{
|
{
|
||||||
using var http = new HttpClient();
|
var input = string.IsNullOrEmpty(settings.Input)
|
||||||
|
? _environment.WorkingDirectory
|
||||||
|
: new DirectoryPath(settings.Input);
|
||||||
|
|
||||||
var htmlStream = await http.GetStreamAsync(url);
|
var file = _fileSystem.File.Retrieve(input.CombineWithFilePath("emoji-list.html"));
|
||||||
|
if (!file.Exists)
|
||||||
|
{
|
||||||
|
using var http = new HttpClient();
|
||||||
|
using var httpStream = await http.GetStreamAsync("http://www.unicode.org/emoji/charts/emoji-list.html");
|
||||||
|
using var outStream = file.OpenWrite();
|
||||||
|
|
||||||
var document = await _parser.ParseDocumentAsync(htmlStream);
|
await httpStream.CopyToAsync(outStream);
|
||||||
|
}
|
||||||
|
|
||||||
return Emoji.Parse(document).OrderBy(x => x.Name).ToList();
|
return file.OpenRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<string> RenderTemplate(Path path, IReadOnlyCollection<Emoji> emojis)
|
private static async Task<string> RenderTemplate(Path path, IReadOnlyCollection<Emoji> emojis)
|
||||||
@ -63,7 +84,6 @@ namespace Generator.Commands
|
|||||||
var text = await File.ReadAllTextAsync(path.FullPath);
|
var text = await File.ReadAllTextAsync(path.FullPath);
|
||||||
|
|
||||||
var template = Template.Parse(text);
|
var template = Template.Parse(text);
|
||||||
|
|
||||||
var templateContext = new TemplateContext
|
var templateContext = new TemplateContext
|
||||||
{
|
{
|
||||||
// Because of the insane amount of Emojis,
|
// Because of the insane amount of Emojis,
|
||||||
@ -72,9 +92,7 @@ namespace Generator.Commands
|
|||||||
};
|
};
|
||||||
|
|
||||||
var scriptObject = new ScriptObject();
|
var scriptObject = new ScriptObject();
|
||||||
|
|
||||||
scriptObject.Import(new { Emojis = emojis });
|
scriptObject.Import(new { Emojis = emojis });
|
||||||
|
|
||||||
templateContext.PushGlobal(scriptObject);
|
templateContext.PushGlobal(scriptObject);
|
||||||
|
|
||||||
return await template.RenderAsync(templateContext);
|
return await template.RenderAsync(templateContext);
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
<None Update="Templates\ColorPalette.Generated.template">
|
<None Update="Templates\ColorPalette.Generated.template">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Templates\Emoji.Json.template">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Update="Templates\Emoji.Generated.template">
|
<None Update="Templates\Emoji.Generated.template">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
@ -31,6 +34,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AngleSharp" Version="0.14.0" />
|
<PackageReference Include="AngleSharp" Version="0.14.0" />
|
||||||
|
<PackageReference Include="Humanizer.Core" Version="2.8.26" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="Scriban" Version="2.1.3" />
|
<PackageReference Include="Scriban" Version="2.1.3" />
|
||||||
<PackageReference Include="Spectre.Cli" Version="0.36.1-preview.0.6" />
|
<PackageReference Include="Spectre.Cli" Version="0.36.1-preview.0.6" />
|
||||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
using AngleSharp.Html.Dom;
|
using AngleSharp.Html.Dom;
|
||||||
|
using Humanizer;
|
||||||
|
|
||||||
namespace Generator.Models
|
namespace Generator.Models
|
||||||
{
|
{
|
||||||
@ -10,15 +11,22 @@ namespace Generator.Models
|
|||||||
{
|
{
|
||||||
private static readonly string[] _headers = { "count", "code", "sample", "name" };
|
private static readonly string[] _headers = { "count", "code", "sample", "name" };
|
||||||
|
|
||||||
private Emoji(string code, string name)
|
private Emoji(string identifier, string name, string code, string description)
|
||||||
{
|
{
|
||||||
Code = code;
|
Identifier = identifier;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
Code = code;
|
||||||
|
Description = description;
|
||||||
|
NormalizedCode = Code.Replace("\\U", "U+");
|
||||||
|
HasCombinators = Code.Split(new[] { "\\U" }, System.StringSplitOptions.RemoveEmptyEntries).Length > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Identifier { get; set; }
|
||||||
public string Code { get; }
|
public string Code { get; }
|
||||||
|
public string NormalizedCode { get; }
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public bool HasCombinators { get; set; }
|
||||||
|
|
||||||
public static IEnumerable<Emoji> Parse(IHtmlDocument document)
|
public static IEnumerable<Emoji> Parse(IHtmlDocument document)
|
||||||
{
|
{
|
||||||
@ -30,13 +38,24 @@ namespace Generator.Models
|
|||||||
foreach (var row in rows)
|
foreach (var row in rows)
|
||||||
{
|
{
|
||||||
var dictionary = _headers
|
var dictionary = _headers
|
||||||
.Zip(row.Cells, (header, cell) => (header, cell.TextContent.Trim()))
|
.Zip(row.Cells, (header, cell) => (Header: header, cell.TextContent.Trim()))
|
||||||
.ToDictionary(x => x.Item1, x => x.Item2);
|
.ToDictionary(x => x.Item1, x => x.Item2);
|
||||||
|
|
||||||
var code = TransformCode(dictionary["code"]);
|
var code = TransformCode(dictionary["code"]);
|
||||||
var name = TransformName(dictionary["name"]);
|
var identifier = TransformName(dictionary["name"])
|
||||||
|
.Replace("-", "_")
|
||||||
|
.Replace("(", string.Empty)
|
||||||
|
.Replace(")", string.Empty);
|
||||||
|
|
||||||
yield return new Emoji(code, name);
|
var description = dictionary["name"].Humanize();
|
||||||
|
|
||||||
|
var name = identifier
|
||||||
|
.Replace("1st", "first")
|
||||||
|
.Replace("2nd", "second")
|
||||||
|
.Replace("3rd", "third")
|
||||||
|
.Pascalize();
|
||||||
|
|
||||||
|
yield return new Emoji(identifier, name, code, description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,8 +67,14 @@ namespace Generator.Models
|
|||||||
.Replace("\u201c", string.Empty)
|
.Replace("\u201c", string.Empty)
|
||||||
.Replace("\u201d", string.Empty)
|
.Replace("\u201d", string.Empty)
|
||||||
.Replace("\u229b", string.Empty)
|
.Replace("\u229b", string.Empty)
|
||||||
.Trim()
|
|
||||||
.Replace(' ', '_')
|
.Replace(' ', '_')
|
||||||
|
.Replace("’s", "s")
|
||||||
|
.Replace("’", "_")
|
||||||
|
.Replace("&", "and")
|
||||||
|
.Replace("#", "hash")
|
||||||
|
.Replace("*", "star")
|
||||||
|
.Replace("!", string.Empty)
|
||||||
|
.Trim()
|
||||||
.ToLowerInvariant();
|
.ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
|
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
|
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
|
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
|
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@ -10,20 +10,34 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Utility class for working with emojis.
|
/// Utility for working with emojis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static partial class Emoji
|
public static partial class Emoji
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, string> _emojis
|
private static readonly Dictionary<string, string> _emojis
|
||||||
= new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
|
= new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
|
||||||
{
|
{
|
||||||
{{~ for emoji in emojis }} { "{{ emoji.name }}", "{{ emoji.code }}" },
|
{{~ for emoji in emojis ~}}
|
||||||
|
{ "{{ emoji.identifier }}", Emoji.Known.{{ emoji.name }} },
|
||||||
{{~ end ~}}
|
{{~ end ~}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains all predefined emojis.
|
||||||
|
/// </summary>
|
||||||
|
public static class Known
|
||||||
|
{
|
||||||
|
{{- for emoji in emojis }}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the "{{ emoji.identifier }}" emoji.
|
||||||
|
/// Description: {{ emoji.description }}.
|
||||||
|
/// </summary>
|
||||||
|
public const string {{ emoji.name }} = "{{ emoji.code }}";
|
||||||
|
{{~ end ~}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
resources/scripts/Generator/Templates/Emoji.Json.template
Normal file
10
resources/scripts/Generator/Templates/Emoji.Json.template
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[
|
||||||
|
{{~ for x in 0..(emojis.size-1) ~}}
|
||||||
|
{
|
||||||
|
"id": "{{ emojis[x].identifier }}",
|
||||||
|
"name": "{{ emojis[x].name }}",
|
||||||
|
"description": "{{ emojis[x].description }}",
|
||||||
|
"code": "{{ emojis[x].normalized_code }}"
|
||||||
|
}{{ if x != (emojis.size-1) }},{{ end }}
|
||||||
|
{{~ end ~}}
|
||||||
|
]
|
44
src/Spectre.Console.Tests/Unit/EmojiTests.cs
Normal file
44
src/Spectre.Console.Tests/Unit/EmojiTests.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using Shouldly;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Tests.Unit
|
||||||
|
{
|
||||||
|
public sealed class EmojiTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Should_Substitute_Emoji_Shortcodes_In_Markdown()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
var console = new TestableAnsiConsole(ColorSystem.Standard, AnsiSupport.Yes);
|
||||||
|
|
||||||
|
// When
|
||||||
|
console.Markup("Hello :globe_showing_europe_africa:!");
|
||||||
|
|
||||||
|
// Then
|
||||||
|
console.Output.ShouldBe("Hello 🌍!");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_Contain_Predefined_Emojis()
|
||||||
|
{
|
||||||
|
// Given, When
|
||||||
|
const string result = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica + "!";
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result.ShouldBe("Hello 🌍!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class TheReplaceMethod
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Should_Replace_Emojis_In_Text()
|
||||||
|
{
|
||||||
|
// Given, When
|
||||||
|
var result = Emoji.Replace("Hello :globe_showing_europe_africa:!");
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result.ShouldBe("Hello 🌍!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borders", "..\examples\Bord
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "..\examples\Links\Links.csproj", "{6AF8C93B-AA41-4F44-8B1B-B8D166576174}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "..\examples\Links\Links.csproj", "{6AF8C93B-AA41-4F44-8B1B-B8D166576174}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -163,6 +165,18 @@ Global
|
|||||||
{6AF8C93B-AA41-4F44-8B1B-B8D166576174}.Release|x64.Build.0 = Release|Any CPU
|
{6AF8C93B-AA41-4F44-8B1B-B8D166576174}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{6AF8C93B-AA41-4F44-8B1B-B8D166576174}.Release|x86.ActiveCfg = Release|Any CPU
|
{6AF8C93B-AA41-4F44-8B1B-B8D166576174}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{6AF8C93B-AA41-4F44-8B1B-B8D166576174}.Release|x86.Build.0 = Release|Any CPU
|
{6AF8C93B-AA41-4F44-8B1B-B8D166576174}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -176,6 +190,7 @@ Global
|
|||||||
{225CE0D4-06AB-411A-8D29-707504FE53B3} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
{225CE0D4-06AB-411A-8D29-707504FE53B3} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||||
{094245E6-4C94-485D-B5AC-3153E878B112} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
{094245E6-4C94-485D-B5AC-3153E878B112} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||||
{6AF8C93B-AA41-4F44-8B1B-B8D166576174} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
{6AF8C93B-AA41-4F44-8B1B-B8D166576174} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||||
|
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C}
|
SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated 2020-08-03 15:17
|
// Generated 2020-09-18 10:42
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,9 +3,9 @@ using System.Text.RegularExpressions;
|
|||||||
namespace Spectre.Console
|
namespace Spectre.Console
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Utility class for working with emojis.
|
/// Utility for working with emojis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static partial class Emoji
|
public static partial class Emoji
|
||||||
{
|
{
|
||||||
private static readonly Regex _emojiCode = new Regex(@"(:(\S*?):)", RegexOptions.Compiled);
|
private static readonly Regex _emojiCode = new Regex(@"(:(\S*?):)", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated 2020-08-03 15:17
|
// Generated 2020-09-18 10:42
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Generated 2020-08-03 15:17
|
// Generated 2020-09-18 10:42
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
|
@ -8,6 +8,12 @@ namespace Spectre.Console.Internal
|
|||||||
{
|
{
|
||||||
public static Paragraph Parse(string text, Style? style = null)
|
public static Paragraph Parse(string text, Style? style = null)
|
||||||
{
|
{
|
||||||
|
if (text is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
text = Emoji.Replace(text);
|
||||||
style ??= Style.Plain;
|
style ??= Style.Plain;
|
||||||
|
|
||||||
var result = new Paragraph();
|
var result = new Paragraph();
|
||||||
|
@ -71,7 +71,7 @@ namespace Spectre.Console.Rendering
|
|||||||
throw new ArgumentNullException(nameof(text));
|
throw new ArgumentNullException(nameof(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
Text = Emoji.Replace(text).NormalizeLineEndings();
|
Text = text.NormalizeLineEndings();
|
||||||
Style = style;
|
Style = style;
|
||||||
IsLineBreak = lineBreak;
|
IsLineBreak = lineBreak;
|
||||||
IsWhiteSpace = string.IsNullOrWhiteSpace(text);
|
IsWhiteSpace = string.IsNullOrWhiteSpace(text);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user