using System.Text; using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; namespace X10D.SourceGenerator; [Generator] internal sealed class EmojiRegexGenerator : ISourceGenerator { // ReSharper disable once IdentifierTypo private const string TwemojiRegexUrl = "https://raw.githubusercontent.com/twitter/twemoji-parser/master/src/lib/regex.js"; private static readonly HttpClient HttpClient = new(); private string _emojiRegex = string.Empty; /// public void Initialize(GeneratorInitializationContext context) { string response = HttpClient.GetStringAsync(TwemojiRegexUrl).GetAwaiter().GetResult(); using var reader = new StringReader(response); while (reader.ReadLine() is { } line) { if (!line.StartsWith("export default /")) { continue; } Match match = Regex.Match(line, @"export default /(?.+)/g;"); if (!match.Success) { continue; } _emojiRegex = $"^{match.Groups["regex"].Value}$"; break; } } /// public void Execute(GeneratorExecutionContext context) { if (string.IsNullOrEmpty(_emojiRegex)) { return; } var builder = new StringBuilder(); builder.AppendLine("// This file was auto-generated by X10D.SourceGenerator"); builder.AppendLine("// Do not edit this file manually"); builder.AppendLine(); builder.AppendLine("using System.Text.RegularExpressions;"); builder.AppendLine(); builder.AppendLine("namespace X10D.Text;"); builder.AppendLine(); builder.AppendLine("internal static class EmojiRegex"); builder.AppendLine("{"); builder.AppendLine(" internal static readonly Regex Value = new Regex("); builder.AppendLine($" @\"{_emojiRegex}\","); // ReSharper disable once StringLiteralTypo builder.AppendLine(" RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Singleline"); builder.AppendLine(" );"); builder.AppendLine("}"); context.AddSource("EmojiRegex.g.cs", SourceText.From(builder.ToString(), Encoding.UTF8)); } }