public static string JoinArgs(this IEnumerable <string> args) { StringBuilder argsStringBuilder = new StringBuilder(); foreach (string arg in args) { if (arg.IsNullOrEmpty()) { continue; } // Escape escape characters (if not on Windows) and quotation marks string escapedArg = OperatingSystem.IsWindows() ? arg.Replace("\"", "\\\"") : arg.Replace("\\", "\\\\").Replace("\"", "\\\""); // Separate with spaces if (!argsStringBuilder.IsEmpty()) { argsStringBuilder.Append(' '); } // Handle spaces by surrounding with quotes if (escapedArg.Contains(' ')) { argsStringBuilder.Append('"'); argsStringBuilder.Append(escapedArg); argsStringBuilder.Append('"'); } else { argsStringBuilder.Append(escapedArg); } } return(argsStringBuilder.ToString()); }
public static async Task <string> GetInputLineOld(Server server, CancellationToken cancellationToken) { StringBuilder message = new StringBuilder(); while (true) { await WaitForKey(cancellationToken); ConsoleKeyInfo key = Console.ReadKey(server.ServerConfig.HideInput.Value); switch (key.Key) { case ConsoleKey.Backspace: if (!message.IsEmpty()) { message.Remove(message.Length - 1, 1); } break; case ConsoleKey.Enter: return(message.ToString()); default: message.Append(key.KeyChar); break; } } }
private void UpdateKeyInfo(KeyPressedInfo currentKey) { var value = new StringBuilder(); if ((currentKey.Modifiers & KeyModifiers.Shift) > 0) { value.Append("Shift"); } if ((currentKey.Modifiers & KeyModifiers.Alt) > 0) { if (!value.IsEmpty()) { value.Append(" + "); } value.Append("Alt"); } if ((currentKey.Modifiers & KeyModifiers.Control) > 0) { if (!value.IsEmpty()) { value.Append(" + "); } value.Append("Control"); } if (currentKey.KeyCode.IsSystemKey()) { if (!value.IsEmpty()) { value.Append(" + "); } value.Append(currentKey.KeyCode.GetString()); } else if (currentKey.KeyValue > 0) { if (!value.IsEmpty()) { value.Append(" + "); } value.Append(Convert.ToChar(MapVirtualKeyEx((uint)currentKey.KeyValue, 2, GetKeyboardLayout(0))).ToString()); } Text = value.ToString(); Invalidate(); }
public void WhenIsEmpty_ThenReturnTrue() { var sut = new StringBuilder(); var result = sut.IsEmpty(); Assert.That(result, Is.True); }
internal static StringBuilder AppendSeparatedIfNotEmpty(this StringBuilder stringBuilder, string separator, string stringToAppend) { if (!stringBuilder.IsEmpty()) { stringBuilder.Append(separator); } return(stringBuilder.Append(stringToAppend)); }
public void StringBuilder_Initialized_Should_Be_Empty() { var stringBuilder = new StringBuilder(); var flag = stringBuilder.IsEmpty(); Assert.True(flag); }
public void IsEmpty_InvokedOnNullReference_ShouldThrowNullReferenceException() { StringBuilder builder = null; Action isEmptyAction = () => { var isEmpty = builder.IsEmpty(); }; isEmptyAction.Should().Throw <NullReferenceException>(); }
public void IsEmpty_ObjectWithWhiteSpace_ShouldReturnFalse(string whiteSpace) { StringBuilder builder = new StringBuilder(whiteSpace); var isEmpty = builder.IsEmpty(); isEmpty.Should().BeFalse(); }
public void IsEmpty_CreateObjectWithInitText_ShouldReturnFalse() { StringBuilder builder = new StringBuilder("test"); var isEmpty = builder.IsEmpty(); isEmpty.Should().BeFalse(); }
public void IsEmpty_CreateObjectWithDefaultConstructor_ShouldReturnTrue() { StringBuilder builder = new StringBuilder(); var isEmpty = builder.IsEmpty(); isEmpty.Should().BeTrue(); }
/// <summary> /// Ajoute la chaîne <paramref name="str"/> au <paramref name="stringBuilder"/> si <paramref name="stringBuilder"/> non vide /// </summary> /// <param name="stringBuilder">StringBuilder</param> /// <param name="str">Chaîne à ajouter au <paramref name="stringBuilder"/></param> /// <returns>StringBuilder</returns> public static StringBuilder AppendIfNotEmpty(this StringBuilder stringBuilder, String str) { if (!stringBuilder.IsEmpty()) { stringBuilder.Append(str); } return(stringBuilder); }
public void StringBuilder_Initialized_With_Append_Should_Not_Be_Empty() { var stringBuilder = new StringBuilder(); stringBuilder.Append("abc123"); var flag = stringBuilder.IsEmpty(); Assert.False(flag); }
/// <summary> /// Заменяет служебные символы HTML на их аналоги исключая '"'. /// </summary> /// <param name="sb">Исходный текст.</param> /// <returns>Результат.</returns> public static StringBuilder ReplaceTagsWQ(this StringBuilder sb) { return (sb.IsEmpty() ? sb : _ampersandDetector .Replace(sb, "&") .Replace(">", ">") .Replace("<", "<")); }
public void WhenHasText_ThenReturnFalse() { var sut = new StringBuilder(); sut.Append("Test"); var result = sut.IsEmpty(); Assert.That(result, Is.False); }
/// <summary> /// OData to string convertion /// </summary> /// <returns>Query string based on OData protocol</returns> public override string ToString() { var stringBuilder = new StringBuilder(); AppendProperty(ref stringBuilder, "filter", Filter); AppendProperty(ref stringBuilder, "orderby", OrderBy); AppendProperty(ref stringBuilder, "top", Top?.ToString()); AppendProperty(ref stringBuilder, "skip", Skip?.ToString()); AppendProperty(ref stringBuilder, "select", Select); AppendProperty(ref stringBuilder, "expand", Expand); return(stringBuilder.IsEmpty() ? string.Empty : $"?{stringBuilder.ToString()}"); }
private void AppendProperty(ref StringBuilder stringBuilder, string propertyName, string propertyValue) { if (string.IsNullOrEmpty(propertyValue)) { return; } if (!stringBuilder.IsEmpty()) { stringBuilder.Append($"&"); } stringBuilder.Append($"${propertyName}={propertyValue}"); }
/// <summary> /// Получение строкового представления морфологической информации /// </summary> /// <returns>строковое представление морфологической информации</returns> private string GetMorphoString() { StringBuilder result = new StringBuilder(); foreach (var morpho in Morpho) { if (!result.IsEmpty()) { result.Append(RDF.ValueSeparator); } result.Append(MorphoInfoToString(morpho)); } return(result.ToString()); }
protected override string TryParse(ParseContext ctx) { var sb = new StringBuilder(); var conditionForMatch = new Func <char, bool>(c => sb.IsEmpty() ? char.IsLetter(c) : char.IsLetterOrDigit(c) || c == '_'); var clone = ctx.Clone(); foreach (var c in clone) { if (!conditionForMatch(c)) { break; } sb.Append(c); } if (!sb.IsEmpty()) { ctx.ReadUntilPosition(clone.CurrentPosition - 1); } return(sb.ToString().IsEmpty() ? null : sb.ToString()); }
/// <summary> /// Добавление к заданному элементу всех прилагательных цепочки, если они есть /// </summary> /// <param name="element">элемент</param> private void AddAdjectivesAttribute(XElement element) { if (_adjectivesForFilter.Any()) { StringBuilder builder = new StringBuilder(); foreach (string adjective in _adjectivesForFilter) { if (!builder.IsEmpty()) { builder.Append(RDF.ValueSeparator); } builder.Append(adjective); } AddNotEmptyAttribute(element, RDF.Attribute.Adjectives, builder.ToString()); } }
public string Validate <T>(T record, bool thowException = true) { // TODO: colocar essa lógica na geração de código pra melhorar a performance var b = new StringBuilder(); if (columns == null) { columns = DataReflectionUtil.GetMapColumns(typeof(T)); } foreach (var _col in columns) { string propertyName = _col.Value.Name; var col = ColumnInfos[_col.Key]; string columnName = col.ColumnName; PropertyInfo prop = _col.Value; var value = prop.GetValue(record, null); var valueStr = value as string; if (!col.IsIdentity && !columnName.EqualsICIC(TableInfo.SequenceColumn) && value == null && !col.IsNullable) { b.AppendFormat($"Property {propertyName} / Column {col.TableName}.{col.ColumnName} does not allow null\r\n"); } if (!string.IsNullOrEmpty(valueStr)) { if (col.DataType != "CLOB" && col.DataType != "BLOB" && col.DataType != "NCLOB") { if (col.CharacterMaximumLength != 0 && valueStr.Length > col.CharacterMaximumLength) { b.AppendFormat($"Property {propertyName} / Column {col.TableName}.{col.ColumnName} Exceeded maximum allowed length {col.CharacterMaximumLength}. Field is {valueStr.Length} characters long.\r\n"); } } } } if (thowException && !b.IsEmpty()) { throw new Exception(b.ToString()); } return(b.Length == 0 ? null : b.ToString()); }
private string GetPersonName(XElement person) { StringBuilder builder = new StringBuilder(); BlockAttribute[] attributeOrder = new BlockAttribute[] { BlockAttribute.LN, BlockAttribute.FN, BlockAttribute.MN }; foreach (BlockAttribute attribute in attributeOrder) { string value = person.Attribute(attribute); if (!value.IsEmpty()) { if (!builder.IsEmpty()) { builder.Append(" "); } builder.Append(value); } } return(builder.ToString()); }
protected override string TryParse(ParseContext ctx) { var sb = new StringBuilder(); var currArg = ctx.PeekNext(ctx.FindNextCharNotInsideNormalBracket(',', true, forceEntireText: true) - ctx.CurrentPosition); for (var i = 0; i < currArg.Length; i++) { var c = currArg[i]; if (c == ':' && currArg.IndexOf(':', i + 1) == -1) { break; } sb.Append(c); } ctx.ReadNext(sb.Length); return(!sb.IsEmpty() ? sb.ToString() : null); }
public void Test07_NotEmptyStringBuilder() { StringBuilder stringBuilder = new StringBuilder("content"); Assert.IsFalse(stringBuilder.IsEmpty()); }
internal bool ParseFamily(ref nsCSSValue aValue) { var family = new StringBuilder(); bool single = false; // keywords only have meaning in the first position if (!ParseOneFamily(family, ref single)) return false; // check for keywords, but only when keywords appear by themselves // i.e. not in compounds such as font-family: default blah; if (single) { nsCSSKeyword keyword = nsCSSKeywords.LookupKeyword(family); if (keyword == nsCSSKeyword.inherit) { aValue.SetInheritValue(); return true; } // 605231 - don't parse unquoted 'default' reserved keyword if (keyword == nsCSSKeyword.@default) { return false; } if (keyword == nsCSSKeyword._moz_initial || keyword == nsCSSKeyword.initial) { aValue.SetInitialValue(); return true; } if (keyword == nsCSSKeyword._moz_use_system_font && !IsParsingCompoundProperty()) { aValue.SetSystemFontValue(); return true; } } for (;;) { if (!ExpectSymbol(',', true)) break; family.Append(','); var nextFamily = new StringBuilder(); if (!ParseOneFamily(nextFamily, ref single)) return false; // at this point unquoted keywords are not allowed // as font family names but can appear within names if (single) { nsCSSKeyword keyword = nsCSSKeywords.LookupKeyword(nextFamily); switch (keyword) { case nsCSSKeyword.inherit: case nsCSSKeyword.initial: case nsCSSKeyword.@default: case nsCSSKeyword._moz_initial: case nsCSSKeyword._moz_use_system_font: return false; default: break; } } family.Append(nextFamily); } if (family.IsEmpty()) { return false; } aValue.SetStringValue(family, nsCSSUnit.Families); return true; }
private void UpdateKeyInfo(KeyPressedInfo currentKey) { var value = new StringBuilder(); if ((currentKey.Modifiers & KeyModifiers.Shift) > 0) value.Append("Shift"); if ((currentKey.Modifiers & KeyModifiers.Alt) > 0) { if(!value.IsEmpty()) value.Append(" + "); value.Append("Alt"); } if ((currentKey.Modifiers & KeyModifiers.Control) > 0) { if (!value.IsEmpty()) value.Append(" + "); value.Append("Control"); } if (currentKey.KeyCode.IsSystemKey()) { if (!value.IsEmpty()) value.Append(" + "); value.Append(currentKey.KeyCode.GetString()); } else if (currentKey.KeyValue > 0) { if (!value.IsEmpty()) value.Append(" + "); value.Append(Convert.ToChar(MapVirtualKeyEx((uint) currentKey.KeyValue, 2, GetKeyboardLayout(0))).ToString()); } Text = value.ToString(); Invalidate(); }
public static bool IsNullOrEmpty(this StringBuilder stringBuilder) { return(stringBuilder?.IsEmpty() ?? true); }
public static StringSections FromString(string fullString, int sectionLength, ColoredMessage leftIndicator = null, ColoredMessage rightIndicator = null, ColoredMessage sectionBase = null) { List <StringSection> sections = new List <StringSection>(); if (string.IsNullOrEmpty(fullString)) { return(new StringSections(sections.ToArray())); } // If the section base message is null, create a default one if (sectionBase == null) { sectionBase = new ColoredMessage(null); } // The starting index of the current section being created int sectionStartIndex = 0; // The text of the current section being created StringBuilder curSecBuilder = new StringBuilder(); for (int i = 0; i < fullString.Length; i++) { curSecBuilder.Append(fullString[i]); // If the section is less than the smallest possible section size, skip processing if (curSecBuilder.Length < sectionLength - ((leftIndicator?.Length ?? 0) + (rightIndicator?.Length ?? 0))) { continue; } // Decide what the left indicator text should be accounting for the leftmost section ColoredMessage leftIndicatorSection = sections.Count > 0 ? leftIndicator : null; // Decide what the right indicator text should be accounting for the rightmost section ColoredMessage rightIndicatorSection = i < fullString.Length - (1 + (rightIndicator?.Length ?? 0)) ? rightIndicator : null; // Check the section length against the final section length if (curSecBuilder.Length >= sectionLength - ((leftIndicatorSection?.Length ?? 0) + (rightIndicatorSection?.Length ?? 0))) { // Copy the section base message and replace the text ColoredMessage section = sectionBase.Clone(); section.text = curSecBuilder.ToString(); // Instantiate the section with the final parameters sections.Add(new StringSection(section, leftIndicatorSection, rightIndicatorSection, sectionStartIndex, i)); // Reset the current section being worked on curSecBuilder.Clear(); sectionStartIndex = i + 1; } } // If there's still text remaining in a section that hasn't been processed, add it as a section if (!curSecBuilder.IsEmpty()) { // Only decide for the left indicator, as this last section will always be the rightmost section ColoredMessage leftIndicatorSection = sections.Count > 0 ? leftIndicator : null; // Copy the section base message and replace the text ColoredMessage section = sectionBase.Clone(); section.text = curSecBuilder.ToString(); // Instantiate the section with the final parameters sections.Add(new StringSection(section, leftIndicatorSection, null, sectionStartIndex, fullString.Length)); } return(new StringSections(sections.ToArray())); }
public static bool IsNotEmpty(this StringBuilder sb) { return(!sb.IsEmpty()); }
/// <summary> /// �������������� ������. /// <b>������������������!</b> /// </summary> /// <param name="txt">�������� �����.</param> /// <param name="smile">������� ��������� ���������.</param> /// <param name="doNotReplaceTags">�� �������� ��������� ������� HTML.</param> /// <param name="doNotFormatImplicitLinks">�� ������������� ���� �� ��������� ������.</param> /// <returns>���������������� �����.</returns> public virtual string Format( string txt, bool smile, bool doNotReplaceTags, bool doNotFormatImplicitLinks) { var sb = new StringBuilder(txt); sb.Trim(TrimArray); if (sb.IsEmpty()) return ""; // ��������! ������� �������������� �����. // // ������ ������������ �������� if (!doNotReplaceTags) sb = sb.ReplaceTagsWQ(); // ���������� ���� ����� ������ ����� � \n // sb = _rxNewLineUnifier.Replace(sb, "\n"); // ��������� �������� ����� � �����, // ������� �� ����� ���� ������ ����������. // // temporary remove [code...] tags const string codeExpression = "$$code{0}$$"; var codeMatcher = new Matcher(codeExpression); sb = _rxCodeFormatting.Replace(sb, codeMatcher.Match); // temporary remove [img] tags const string imgExpression = "$$img{0}$$"; var imgMatcher = new Matcher(imgExpression); sb = _imgTagRegex.Replace(sb, imgMatcher.Match); // temporary remove [url] & [purl] tags const string urlExpression = "$$url{0}$$"; var urlMatcher = new Matcher(urlExpression); sb = _urlTagRegex.Replace(sb, urlMatcher.Match); // temporary remove implicit links const string implicitUrlExpression = "$$iurl{0}$$"; var implicitUrlMatcher = new Matcher(implicitUrlExpression); if (!doNotFormatImplicitLinks) sb = _urlRegex.Replace(sb, implicitUrlMatcher.Match); // temporary remove [q] tags const string quoteExpression = "$$quote{0}$$"; var quoteMatcher = new Matcher(quoteExpression); sb = _rxPrep12.Replace(sb, quoteMatcher.Match); // temporary remove [cut] tags const string cutExpression = "$$cut{0}$$"; Matcher cutMatcher; do { cutMatcher = new Matcher(cutExpression); sb = _rxPrep13.Replace(sb, cutMatcher.Match); // �����������. sb = _rxTextUrl09.Replace(sb, "<span class='lineQuote'>$&</span>"); // restore & transform [cut] tags for (var i = 0; i < cutMatcher.Count; i++) { var m = cutMatcher[i]; var capt = String.IsNullOrEmpty(m.Groups[3].Value) ? "������� �����" : m.Groups[3].Value; sb = sb.Replace(String.Format(cutExpression, i), _hiddenTextSnippet.Replace("%CAPT%", capt).Replace("%TEXT%", m.Groups[4].Value). Replace("%URL%", GetImagePrefix())); } } while (cutMatcher.Count > 0); // restore & transform [q] tags // ����������� [q]. // http://www.rsdn.ru/forum/?mid=111506 for (var i = 0; i < quoteMatcher.Count; i++) sb = sb.Replace( string.Format(quoteExpression, i), string.Format( "<blockquote class='q'><p>{0}</p></blockquote>", quoteMatcher[i].Groups[1])); // ��������� ��������� � ������ ������ � http://www.rsdn.ru/forum/?mid=184751 if (smile) { var prefix = GetImagePrefix(); sb = _smileReplacers.Aggregate( sb, (current, replacer) => replacer.Replace(current, prefix)); } // ISBN sb = _isbnDetector.Replace( sb, match => { var isbn = new StringBuilder(match.Length); foreach (Capture capture in match.Groups["isbn"].Captures) { isbn.Append(capture.Value).Append('-'); } if (isbn.Length > 0) isbn.Length--; return ProcessISBN(match, isbn.ToString()); }); // restore & transform [url] and [purl] tags for (var i = 0; i < urlMatcher.Count; i++) { var url = urlMatcher[i].Groups["url"].Value; var tag = urlMatcher[i].Groups["tag"].Value; // ���� url � tag ����������: // if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) // ���� tag �� ������ // if (!String.IsNullOrEmpty(tag)) // ���� tag ���������� Uri // if (Uri.IsWellFormedUriString(tag, UriKind.RelativeOrAbsolute)) { // // var temp = tag; tag = url; url = temp; } sb = sb.Replace( string.Format(urlExpression, i), ProcessURLs(url, tag)); } // restore & transform implicit links for (var i = 0; i < implicitUrlMatcher.Count; i++) sb = sb.Replace( string.Format(implicitUrlExpression, i), ProcessImplicitURLs(implicitUrlMatcher[i])); // restore & transform [img] tags for (var i = 0; i < imgMatcher.Count; i++) sb = sb.Replace( string.Format(imgExpression, i), ImagesDelegate(this, imgMatcher[i])); // RSDN links sb = _rsdnLinkDetector.Replace(sb, ProcessRsdnLink); // [email] sb = _emailTagRegex.Replace(sb, ProcessEmailLink); // Replace hyphen to dash sb = _dashDetector.Replace(sb, "—"); // [tagline] sb = _taglineDetector.Replace(sb, "<div class='tagline'>$1</div>"); // [list] sb = _rxPrep06.Replace(sb, @"<ul style='margin-top:0; margin-bottom:0;'>$1</ul>"); // [list=..] sb = _rxPrep07.Replace(sb, ListEvaluator); // [*] sb = _rxPrep08.Replace(sb, "<li />"); // [hr] sb = _rxPrep09.Replace(sb, "<hr />"); // Q12345(6) sb = _rxPrep10.Replace( sb, @"<a target='_blank' class='m' href='http://support.microsoft.com/default.aspx?scid=kb;EN-US;$1'>$1</a>"); // ��������� ����������. sb = _moderatorDetector.Replace(sb, "<div class='mod'>$1</div>"); // Table sb = _rxTable.Replace( sb, "<table class='formatter' border='0' cellspacing='2' cellpadding='5'>$1</table>"); sb = _rxTableRow.Replace(sb, "<tr class='formatter'>$1</tr>"); sb = _rxTableHeader.Replace(sb, "<th class='formatter'>$1</th>"); sb = _rxTableColumn.Replace(sb, "<td class='formatter'>$1</td>"); // Headers sb = _rxHeaders.Replace(sb, "<h$2 class='formatter'>$1</h$2>"); // ��������� � ����� ������ ������ <br />, // �� �� ����� </table>, </div>, </ol>, </ul>, <blockquote> (�������� ������ <span>) // � �� � ����� ����� ������ sb = _rxNewLines.Replace(sb, "<br />$0"); sb = _inlineTagReplacers.Aggregate(sb, (cur, replacer) => replacer(cur)); // ������ �� MSDN. sb = _rxMsdn.Replace(sb, DoMSDNRef); // ����� ��� ������ ����� � ������ ���������. sb = _rxPrep01.Replace(sb, ""); sb = _rxPrep02.Replace(sb, ""); sb = _rxPrep03.Replace(sb, ""); // restore & transform [code] tags for (var i = 0; i < codeMatcher.Count; i++) { // code coloring var code = PaintCode(codeMatcher[i]); // bold & italic formatting inside code // without checking canceling tag syntax code = _inlineTagReplacersNoChecks.Aggregate(code, (cur, replacer) => replacer(cur)); sb = sb.Replace(string.Format(codeExpression, i), code.ToString()); } return sb.ToString(); }
public void Test01_NullStringBuilder() { StringBuilder testBuilder = default; Assert.ThrowsException <ArgumentNullException>(() => testBuilder.IsEmpty()); }
public static bool IsNotEmpty(this StringBuilder buf) { return(!buf.IsEmpty()); }
public void Test04_EmptyStringBuilder() { StringBuilder stringBuilder = new StringBuilder(); Assert.IsTrue(stringBuilder.IsEmpty()); }
public static string Clean(string name, char wordsSeparator = '.') { if (name.IsNullOrEmpty()) { return(name); } var array = name.Split(PUNCTUATION_CHARS, StringSplitOptions.RemoveEmptyEntries); #region [.phase #1.] var firstWholeNumbersWord = default(string); var words = new List <(string word, bool isOnlyLetters)>(array.Length); foreach (var s in array) { if (EXCLUDES_WORDS_SET.Contains(s)) { continue; } if (int.TryParse(s, out var _)) { if (firstWholeNumbersWord == null) { firstWholeNumbersWord = s; } continue; } words.Add((s, s.IsOnlyLetters())); } if (!words.Any()) { var s = (firstWholeNumbersWord ?? "---"); words.Add((s, s.IsOnlyLetters())); } #endregion #region [.phase #2.] const char SPACE = ' '; var sb = new StringBuilder(name.Length); var prev_word_isOnlyLetters = true; foreach (var t in words) { if (t.word.TryParseSE(out var se)) { if (!sb.IsEmpty()) { sb.ReplaceLastCharIfNotEqual(wordsSeparator); } sb.Append(se).Append(wordsSeparator); break; } if (prev_word_isOnlyLetters) //&& t.isOnlyLetters ) { sb.AppendFirstCharToUpper(t.word).Append((t.isOnlyLetters ? SPACE : wordsSeparator)); } else { sb.Append(t.word).Append(wordsSeparator); } prev_word_isOnlyLetters = t.isOnlyLetters; } sb.RemoveLastChar(); #endregion return(sb.ToString()); }
/// <summary> /// Форматирование текста. /// <b>НЕПОТОКОБЕЗОПАСНЫЙ!</b> /// </summary> /// <param name="txt">Исходный текст.</param> /// <param name="smile">Признак обработки смайликов.</param> /// <param name="doNotReplaceTags">Не заменять служебные символы HTML.</param> /// <param name="doNotFormatImplicitLinks">Не форматировать явно не указанные ссылки.</param> /// <returns>Сформатированный текст.</returns> public virtual string Format( string txt, bool smile, bool doNotReplaceTags, bool doNotFormatImplicitLinks) { var sb = new StringBuilder(txt); sb.Trim(TrimArray); if (sb.IsEmpty()) return ""; // Внимание! Порядок преобразования ВАЖЕН. // // Замена небезопасных символов if (!doNotReplaceTags) sb = sb.ReplaceTagsWQ(); // Приведение всех типов концов строк к \n // sb = _rxNewLineUnifier.Replace(sb, "\n"); // Обработка исходных кодов и тегов, // которые не могут быть внутри исходников. // // temporary remove [code...] tags const string codeExpression = "$$code{0}$$"; var codeMatcher = new Matcher(codeExpression); sb = _rxCodeFormatting.Replace(sb, codeMatcher.Match); // temporary remove [img] tags const string imgExpression = "$$img{0}$$"; var imgMatcher = new Matcher(imgExpression); sb = _imgTagRegex.Replace(sb, imgMatcher.Match); // temporary remove [url] & [purl] tags const string urlExpression = "$$url{0}$$"; var urlMatcher = new Matcher(urlExpression); sb = _urlTagRegex.Replace(sb, urlMatcher.Match); // temporary remove implicit links const string implicitUrlExpression = "$$iurl{0}$$"; var implicitUrlMatcher = new Matcher(implicitUrlExpression); if (!doNotFormatImplicitLinks) sb = _urlRegex.Replace(sb, implicitUrlMatcher.Match); // temporary remove [q] tags const string quoteExpression = "$$quote{0}$$"; var quoteMatcher = new Matcher(quoteExpression); sb = _rxPrep12.Replace(sb, quoteMatcher.Match); // temporary remove [cut] tags const string cutExpression = "$$cut{0}$$"; Matcher cutMatcher; do { cutMatcher = new Matcher(cutExpression); sb = _rxPrep13.Replace(sb, cutMatcher.Match); // Цитирование. sb = _rxTextUrl09.Replace(sb, m => $"<span class='lineQuote level{WebUtility.HtmlDecode(m.Groups["lev"].Value).Length}'>{m.Groups[0].Value}</span>"); // restore & transform [cut] tags for (var i = 0; i < cutMatcher.Count; i++) { var m = cutMatcher[i]; var capt = String.IsNullOrEmpty(m.Groups[3].Value) ? "Скрытый текст" : m.Groups[3].Value; sb = sb.Replace(String.Format(cutExpression, i), _hiddenTextSnippet.Replace("%CAPT%", capt).Replace("%TEXT%", m.Groups[4].Value). Replace("%URL%", GetImagePrefix())); } } while (cutMatcher.Count > 0); // restore & transform [q] tags // Цитирование [q]. // http://www.rsdn.ru/forum/?mid=111506 for (var i = 0; i < quoteMatcher.Count; i++) sb = sb.Replace( string.Format(quoteExpression, i), $"<blockquote class='q'><p>{quoteMatcher[i].Groups[1]}</p></blockquote>"); // Обработка смайликов с учетом отмены и http://www.rsdn.ru/forum/?mid=184751 if (smile) { var prefix = GetImagePrefix(); sb = _smileReplacers.Aggregate( sb, (current, replacer) => replacer.Replace(current, prefix)); } // ISBN sb = _isbnDetector.Replace( sb, match => { var isbn = new StringBuilder(match.Length); foreach (Capture capture in match.Groups["isbn"].Captures) { isbn.Append(capture.Value).Append('-'); } if (isbn.Length > 0) isbn.Length--; return ProcessISBN(match, isbn.ToString()); }); // restore & transform [url] and [purl] tags for (var i = 0; i < urlMatcher.Count; i++) { var url = urlMatcher[i] .Groups["url"] .Value; var tag = urlMatcher[i].Groups["tag"].Value; // если url и tag перепутаны: // if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)) // если tag не пустой // if (!String.IsNullOrEmpty(tag)) // если tag правильный Uri // if (Uri.IsWellFormedUriString(tag, UriKind.RelativeOrAbsolute)) { // // var temp = tag; tag = url; url = temp; } url = url.Replace("&", "&"); // Returns escaped ampersands sb = sb.Replace( string.Format(urlExpression, i), ProcessURLs(url, tag)); } // restore & transform implicit links for (var i = 0; i < implicitUrlMatcher.Count; i++) sb = sb.Replace( string.Format(implicitUrlExpression, i), ProcessImplicitURLs(implicitUrlMatcher[i])); // restore & transform [img] tags for (var i = 0; i < imgMatcher.Count; i++) sb = sb.Replace( string.Format(imgExpression, i), ImagesDelegate(this, imgMatcher[i])); // RSDN links sb = _rsdnLinkDetector.Replace(sb, ProcessRsdnLink); // [email] sb = _emailTagRegex.Replace(sb, ProcessEmailLink); // Replace hyphen to dash sb = _dashDetector.Replace(sb, "—"); // [tagline] sb = _taglineDetector.Replace(sb, "<div class='tagline'>$1</div>"); // [list] sb = _rxPrep06.Replace(sb, @"<ul style='margin-top:0; margin-bottom:0;'>$1</ul>"); // [list=..] sb = _rxPrep07.Replace(sb, ListEvaluator); // [*] sb = _rxPrep08.Replace(sb, "<li />"); // [hr] sb = _rxPrep09.Replace(sb, "<hr />"); // Q12345(6) sb = _rxPrep10.Replace( sb, @"<a target='_blank' class='m' href='http://support.microsoft.com/default.aspx?scid=kb;EN-US;$1'>$1</a>"); // Сообщение модератора. sb = _moderatorDetector.Replace(sb, "<div class='mod'>$1</div>"); // Table sb = _rxTable.Replace( sb, "<table class='formatter' border='0' cellspacing='2' cellpadding='5'>$1</table>"); sb = _rxTableRow.Replace(sb, "<tr class='formatter'>$1</tr>"); sb = _rxTableHeader.Replace(sb, "<th class='formatter'>$1</th>"); sb = _rxTableColumn.Replace(sb, "<td class='formatter'>$1</td>"); // Headers sb = HeadersRegex.Replace(sb, "<h$2 class='formatter'>$1</h$2>"); // Добавляем в конец каждой строки <br />, // но не после </table>, </div>, </ol>, </ul>, <blockquote> (возможно внутри <span>) // и не в самом конце текста sb = _rxNewLines.Replace(sb, "<br />$0"); sb = _inlineTagReplacers.Aggregate(sb, (cur, replacer) => replacer(cur)); // Ссылки на MSDN. sb = _rxMsdn.Replace(sb, DoMSDNRef); // Нужно для отмены тэгов и отмены смайликов. sb = _rxPrep01.Replace(sb, ""); sb = _rxPrep02.Replace(sb, ""); sb = _rxPrep03.Replace(sb, ""); // restore & transform [code] tags for (var i = 0; i < codeMatcher.Count; i++) { // code coloring var code = PaintCode(codeMatcher[i]); // bold & italic formatting inside code // without checking canceling tag syntax code = _inlineTagReplacersNoChecks.Aggregate(code, (cur, replacer) => replacer(cur)); sb = sb.Replace(string.Format(codeExpression, i), code.ToString()); } return sb.ToString(); }