static void InsertToken(ICollection<Inline> ic, Token t, TextRenderContext ctx) { switch (t.tag) { case TokenTypes.Hyperlink: InsertHyperLink(ic, t); break; case TokenTypes.Name: InsertMentionName(ic, t); break; case TokenTypes.Emotion: InsertEmotion(ic, t); break; case TokenTypes.CopyedFrom: InsertCopyedFrom(ic, t,ctx); break; case TokenTypes.ReplyTo: InsertReplyto(ic, t); break; case TokenTypes.Topic: { InsertTopic(ic, t); } break; case TokenTypes.Quote: { InsertQuote(ic, t); } break; case TokenTypes.Writer: { InsertWriter(ic, t); break; } case TokenTypes.Break: { InsertBreak(ic); break; } //case TokenTypes.End: //case TokenTypes.Punctuation: //case TokenTypes.Part: //case TokenTypes.Reserved: default: InsertNormal(ic, t); break; } }
private static void InsertMentionName(ICollection<Inline> textblock, Token t) { var name = t.text; if (string.IsNullOrEmpty(name)) return; textblock.Add(new Run("@")); var h = new Hyperlink(new Run(name)); //h.SetResourceReference(Control.ForegroundProperty, "MetroColorText"); textblock.Add(h); }
private static void InsertWriter(ICollection<Inline> textblock, Token t) { var name = t.text; if (string.IsNullOrEmpty(name)) return; var run = new Run(t.text); run.SetResourceReference(Control.ForegroundProperty, "MetroColorFeatureBrush"); textblock.Add(run); textblock.Add(new Run(":")); }
private static void InsertEmotion(ICollection<Inline> textblock, Token t) { var emo = t.text.Trim(); if (string.IsNullOrEmpty(emo)) return; textblock.Add(new Run(string.Format("[{0}]", emo))); }
private static void InsertQuote(ICollection<Inline> textblock, Token t) { var q = t.text.Trim(); if (string.IsNullOrEmpty(q)) return; textblock.Add(new Run(string.Format("“{0}”", q))); }
private static void InsertCopyedFrom(ICollection<Inline> textblock, Token t, TextRenderContext ctx) { var name = t.text; if (string.IsNullOrEmpty(name)) return; if(!ctx.HasCopyedFromItem) { ctx.HasCopyedFromItem = true; textblock.Add(new LineBreak()); } textblock.Add(new Run("//@")); var h = new Hyperlink(new Run(name)); //h.SetResourceReference(Control.ForegroundProperty, "MetroColorText"); textblock.Add(h); textblock.Add(new Run(":")); }
private static void InsertTopic(ICollection<Inline> textblock, Token t) { var topic = t.text; if (string.IsNullOrEmpty(topic)) return; textblock.Add(new Run("#")); textblock.Add(new Run(topic)); textblock.Add(new Run("#")); }
private static Token eat_quote(string text, ref int begin, int end, char endchar) { var rtn = new Token {tag = TokenTypes.Quote}; Debug.Assert(is_quote(text[begin])); ++begin; while (begin < end && text[begin] != endchar) { rtn.text += text[begin++]; } if (begin == end) rtn.text = string.Empty; else ++begin; rtn.flag = endchar; return rtn; }
public static List<Token> Parse(this string text) { var rtn = new List<Token>(); var begin = 0; var end = text.Length; var last = new Token(); while (begin < end) { Token t = null; var b = begin; var c = text[begin]; if (c > 0xdfff && c < 0xe900)//忽略自定义字符 { ++begin; continue; } switch (c) { case '/': t = eat_sharedfrom(text, ref b, end); break; case '@': t = eat_name(text, ref b, end); break; case 'h': t = eat_hyperlink(text, ref b, end); break; case '#': t = eat_topic(text, ref b, end, c); break; case '【': t = eat_topic(text, ref b, end, '】'); break; case '《': t = eat_topic(text, ref b, end, '》'); break; case '『': t = eat_topic(text, ref b, end, '』'); break; case '[': t = eat_emotion(text, ref b, end); break; case '回': t = eat_replyto(text, ref b, end); break; case '?': case '。': case '!': case '!': case '~': case ',': case ',': case ';': case ':': case ':': case '.': case '-': t = eat_punctuation(text, ref b, end,c); break; case '"': t = eat_quote(text, ref b, end, '"'); break; case '“': t = eat_quote(text, ref b, end, '”'); break; case '(': t = eat_quote(text, ref b, end, ')'); break; case '(': t = eat_quote(text, ref b, end, '('); break; case '「': t = eat_quote(text, ref b, end, '」'); break; } if (t == null || (string.IsNullOrEmpty(t.text))) //没有匹配上 { last.text += c; ++begin; } else { if (last.text.Length > 0) { rtn.Add(last); last = new Token(); } rtn.Add(t); begin = b; } } if (last.text.Length > 0) { rtn.Add(last); } return rtn; }
private static Token eat_hyperlink(string text, ref int begin, int end) { var rtn = new Token { text = "", tag = TokenTypes.Hyperlink }; const string h = "http://"; var i = text.Substring(begin, (h.Length < end - begin) ? h.Length : (end - begin)); if (String.Compare(h, i, StringComparison.OrdinalIgnoreCase) == 0) { while (begin < end) { char t = text[begin]; if ((char.IsLetterOrDigit(t) && t < 128) || t == '.' || t == '/' || t == ':' || t == '&' || t == '%' || t == '?' || t == '_' || t == '=' || t == '#' || t == '-') rtn.text += t; else break; ++begin; } } return rtn; }
private static Token eat_sharedfrom(string text, ref int beg, int end) { var begin = beg; var rtn = new Token { text = string.Empty, tag = TokenTypes.CopyedFrom }; if (begin + 2 < end && text[begin] == '/' && text[begin + 1] == '/' && text[begin + 2] == '@') { begin += 3; while (begin < end && !char.IsWhiteSpace(text[begin]) && !is_invalid_name_char(text[begin])) { rtn.text += text[begin++]; } } if (begin + 3 < end && text[begin] == '/' && text[begin + 1] == '/' && text[begin + 2] == ' ' && text[begin + 3] == '@') { begin += 4; while (begin < end && !char.IsWhiteSpace(text[begin]) && !is_invalid_name_char(text[begin])) { rtn.text += text[begin++]; } } if (begin < end && (text[begin] == ':' || text[begin] == ':')) ++begin; if (rtn.text.Length > 16) {//最多16个字 rtn.text = string.Empty; } if (!string.IsNullOrEmpty(rtn.text)) beg = begin; return rtn; }
private static Token eat_topic(string text, ref int begin, int end, char endchar) { var rtn = new Token { text = "", tag = TokenTypes.Topic }; ++begin; while (begin < end && text[begin] != endchar) { rtn.text += text[begin++]; } if (begin == end) //cann't find # rtn.text = ""; else ++begin; rtn.text = rtn.text.Trim(); rtn.flag = endchar; return rtn; }
private static Token eat_punctuation(string text, ref int begin, int end, char punc) { var rtn = new Token { text = "", tag = TokenTypes.Punctuation }; while (begin < end && (text[begin].IsPunctuationExt() || char.IsWhiteSpace(text[begin]))) { rtn.text += text[begin++]; } rtn.flag = punc; return rtn; }
private static Token eat_emotion(string text, ref int begin, int end) { var rtn = new Token { text = "", tag = TokenTypes.Emotion }; if (text[begin] == '[') { ++begin; while (begin < end && text[begin] != ']') { rtn.text += text[begin++]; } if (begin == end) //cann't find ] rtn.text = ""; else ++begin; } return rtn; }
//private static bool InsertName(ICollection<Inline> textblock, string name) //{ // if (string.IsNullOrEmpty(name)) // return false; // textblock.Add(new Hyperlink(new Run(name))); // textblock.Add(new Run(":")); // return true; //} private static void InsertHyperLink(ICollection<Inline> textblock, Token token) { var ut = token.text; if (string.IsNullOrEmpty(ut)) return; if (ut.Length != token.text.Length) textblock.Add(new Run(" ")); var run = ut.Replace(Properties.Resources.ShortUrlPrefix, string.Empty); //create hyperlink var h = new Hyperlink(new Run(run){FontWeight = FontWeights.SemiBold}) { // NavigateUri = new Uri(ut,UriKind.Absolute),使用这个会直接调用到navigationservice中 Command = WeiZhiCommands.Navigate, CommandParameter = ut, ToolTip = ut, }; h.ToolTipOpening += (s, e) => { var dp =(Hyperlink) s; if (dp.Tag != null) return; var mem = MemoryCache.Default; var ui = (UrlInfo) mem.Get(ut); if (ui == null) return; dp.Tag = ui; if (!string.IsNullOrEmpty(ui.topic())) dp.ToolTip = ui.topic() + " / " + EnumDescription.Get(ui.type); else dp.ToolTip = ui.url_long + " / " + EnumDescription.Get(ui.type); }; h.SetResourceReference(TextElement.ForegroundProperty, "MetroColorFeatureBrush"); textblock.Add(h); var memc = MemoryCache.Default; var uinfo = (UrlInfo)memc.Get(ut); if (uinfo != null) { if (uinfo.type == UrlType.Video) textblock.Add(new Run("\uE173")); else if (uinfo.type == UrlType.Music) textblock.Add(new Run("\u266C")); } else if (ut.Length != token.text.Length) textblock.Add(new Run(" ")); }
private static void InsertNormal(ICollection<Inline> textblock, Token t) { if (string.IsNullOrEmpty(t.text)) return; textblock.Add(new Run(t.text)); }
private static Token eat_name(string text, ref int begin, int end) { var rtn = new Token { text = "", tag = TokenTypes.Name }; const string h = "http://"; var b = begin; ++begin; while (begin < end && !char.IsWhiteSpace(text[begin]) && !is_invalid_name_char(text[begin])) { if (text[begin] == 'h' && begin + h.Length < end) { var t = text.Substring(begin, h.Length > end - begin ? end - begin : h.Length); if (String.Compare(t, h, StringComparison.OrdinalIgnoreCase) == 0) break; } rtn.text += text[begin++]; } if (rtn.text.Length > 16) { //最多16个字 rtn.text = ""; begin = b; } return rtn; }