using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; namespace FSO.Common.Utils { /// /// In: /// - String Containing BBCode /// /// [color=red]Hello![/color] /// [color=#FF0000]Also [size=20]red[/size][/color] /// \[ escaped \] square brackets. /// /// Out: /// - String Without BBCode /// - Ordered list of BBCodeCommands, and the index in the converted string they occur at. /// public class BBCodeParser { public string Stripped; public List Commands = new List(); public BBCodeParser(string input) { var stripped = new StringBuilder(); int index = 0; while (index < input.Length) { var newIndex = input.IndexOf('[', index); if (newIndex == -1) { newIndex = input.Length; //no more commands. //render the rest of the string and break out. stripped.Append(input.Substring(index, newIndex - index)); break; } stripped.Append(input.Substring(index, newIndex - index)); //we found the start of a bbcode. is it escaped? if (newIndex > 0 && input[newIndex - 1] == '\\') { //draw the bracket. stripped[stripped.Length - 1] = '['; //replace the backslash with the leftbracket index = newIndex + 1; //continue after the bracket } else { //find our right bracket var endIndex = input.IndexOf(']', newIndex); if (endIndex == -1) { //fail safe. stripped.Append('['); index = newIndex + 1; //continue after the bracket } else { Commands.Add(new BBCodeCommand(input.Substring(newIndex + 1, (endIndex - newIndex) - 1), stripped.Length)); index = endIndex + 1; } } } Stripped = stripped.ToString(); } public static string SanitizeBB(string input) { if (input.LastOrDefault() == '\\') input += ' '; return input.Replace("[", "\\["); } } public class BBCodeCommand { public BBCodeCommandType Type; public string Parameter; public int Index; public bool Close; public BBCodeCommand(string cmd, int index) { Index = index; if (cmd[0] == '/') { Close = true; cmd = cmd.Substring(1); } var split = cmd.Split('='); if (split.Length > 1) Parameter = split[1]; System.Enum.TryParse(split[0], out Type); } public Color ParseColor() { if (Parameter == null || Parameter.Length == 0) return Color.White; //todo: search color static members for named colours //for now we only support hex if (Parameter.Length == 7 && Parameter[0] == '#') { uint rgb; if (uint.TryParse(Parameter.Substring(1), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out rgb)) { return new Color((byte)(rgb >> 16), (byte)(rgb >> 8), (byte)(rgb), (byte)255); } } else { var color = typeof(Color).GetProperties().Where(x => x.PropertyType == typeof(Color) && x.Name.ToLowerInvariant() == Parameter.ToLowerInvariant()).FirstOrDefault(); if (color != null) { return (Color)color.GetValue(null); } } return Color.White; } } public enum BBCodeCommandType { unknown, color, size, emoji, s } }