/// <summary>
 /// Получить цитируемые посты.
 /// </summary>
 /// <param name="document">Документ.</param>
 /// <returns>Цитируемые посты.</returns>
 public static IList <ILink> GetQuotes(this IPostDocument document)
 {
     if (document?.Nodes == null)
     {
         return(new List <ILink>());
     }
     return(document.Nodes.FlatHierarchy(n =>
     {
         if (n is ICompositePostNode cn)
         {
             return cn.Children;
         }
         return null;
     }).OfType <IBoardLinkPostNode>().Select(l => l?.BoardLink).Where(l => l != null).ToList());
 }
 private void CheckPostDocumentSerialization <T>(T original, IPostDocument deserialized, Action <T, T> asserts)
     where T : IPostDocument
 {
     Assert.IsNotNull(deserialized, "Десериализованный объект == null");
     Assert.AreNotSame(original, deserialized, "Десериализация вернула тот же объект");
     Assert.IsInstanceOfType(deserialized, typeof(T), $"Тип объекта не {typeof(T).FullName}");
     if (original.Nodes == null)
     {
         Assert.IsNull(deserialized.Nodes, "deserialized.Nodes должно быть не null");
     }
     else
     {
         Assert.IsNotNull(deserialized.Nodes, "deserialized.Nodes не должно быть null");
         Assert.AreNotSame(original.Nodes, deserialized.Nodes, "Должны быть разные объекты");
         Assert.AreEqual(original.Nodes.Count, deserialized.Nodes.Count, "Должно быть равное количество элементов");
     }
     asserts?.Invoke(original, (T)deserialized);
 }
        /// <summary>
        /// Перевести в простой текст.
        /// </summary>
        /// <param name="tree">Дерево поста.</param>
        /// <returns>Текст.</returns>
        public static IList <string> ToPlainText(this IPostDocument tree)
        {
            var context = new { sb = new StringBuilder(), result = new List <string>() };
            var rules   = tree.Nodes.TreeWalk(context)
                          .GetChildren(n => (n as ICompositePostNode)?.Children)
                          .If(n => n is ITextPostNode, (n, ctx) =>
            {
                ctx.sb.Append(((ITextPostNode)n).Text);
                return(ctx);
            })
                          .If(n => IsAttribute(n, PostBasicAttributes.Paragraph) || n is ILineBreakPostNode, (n, ctx) =>
            {
                ctx.result.Add(ctx.sb.ToString());
                ctx.sb.Clear();
                return(ctx);
            })
                          .If(n => n is IBoardLinkPostNode, (n, ctx) =>
            {
                var l  = (IBoardLinkPostNode)n;
                var pl = l.BoardLink as IPostLink;
                var tl = l.BoardLink as IThreadLink;
                if (pl != null)
                {
                    ctx.sb.Append(">>" + pl.GetPostNumberString());
                }
                else if (tl != null)
                {
                    ctx.sb.Append(">>" + tl.GetThreadNumberString());
                }
                return(ctx);
            })
                          .Else((n, c) => c);

            rules.Run();
            if (context.sb.Length > 0)
            {
                context.result.Add(context.sb.ToString());
            }
            return(context.result);
        }
 public static void AssertDocuments(IModuleProvider modules, IPostDocument original, IPostDocument deserialized, int[] path = null, Action <IPostNode, IPostNode> assertCallback = null)
 {
     if (original == null)
     {
         Assert.IsNull(deserialized, "Документ должен быть null");
     }
     else
     {
         Assert.IsNotNull(deserialized, "Документ не должен быть null");
         if (original.Nodes == null)
         {
             Assert.IsNull(deserialized.Nodes, "Узлы документа должны быть null");
         }
         else
         {
             Assert.IsNotNull(deserialized.Nodes, "Узлы документа не должны быть null");
             Assert.AreEqual(original.Nodes.Count, deserialized.Nodes.Count, "Количество узлов документа не совпадает");
             for (var i = 0; i < original.Nodes.Count; i++)
             {
                 AssertNodes(modules, original.Nodes[i], deserialized.Nodes[i], new [] { i + 1 }, assertCallback);
             }
         }
     }
 }