Esempio n. 1
0
        public void TestParagraphWithInlineElement()
        {
            IMarkdownDocument document  = new MarkdownDocument().AppendParagraph(new MarkdownText("Text"));
            MarkdownParagraph paragraph = Assert.IsType <MarkdownParagraph>(document.ElementAt(0));

            Assert.Equal("Text", paragraph.Text);
        }
Esempio n. 2
0
        internal static MarkdownParagraph DotNetCommentsToParagraph(DotNetComment comment, DotNetMember parent = null)
        {
            MarkdownParagraph paragraph = new MarkdownParagraph();

            DotNetCommentsFillParagraph(paragraph, comment, parent);
            return(paragraph);
        }
        public string _loc; // generated lazily.

        public SourceLocation(string file, SectionRef section, MarkdownParagraph paragraph, MarkdownSpan span)
        {
            File      = file;
            Section   = section;
            Paragraph = paragraph;
            Span      = span;
        }
Esempio n. 4
0
    private static int BugWorkaroundIndent(ref MarkdownParagraph mdp, int level)
    {
        if (!mdp.IsParagraph)
        {
            return(level);
        }
        var p     = mdp as MarkdownParagraph.Paragraph;
        var spans = p.Item;

        if (spans.Count() == 0 || !spans[0].IsLiteral)
        {
            return(level);
        }
        var literal = spans[0] as MarkdownSpan.Literal;

        if (!literal.Item.StartsWith("ceci-n'est-pas-une-indent"))
        {
            return(level);
        }
        //
        var literal2 = MarkdownSpan.NewLiteral(literal.Item.Substring(25));
        var spans2   = Microsoft.FSharp.Collections.FSharpList <MarkdownSpan> .Cons(literal2, spans.Tail);

        var p2 = MarkdownParagraph.NewParagraph(spans2);

        mdp = p2;
        return(0);
    }
Esempio n. 5
0
 public FlatItem(int level, bool hasBullet, bool isBulletOrdered, MarkdownParagraph paragraph)
 {
     Level           = level;
     HasBullet       = hasBullet;
     IsBulletOrdered = isBulletOrdered;
     Paragraph       = paragraph;
 }
Esempio n. 6
0
        public void TestIndexOf()
        {
            var document  = new MarkdownDocument();
            var paragraph = new MarkdownParagraph("");

            document.Append(paragraph);

            Assert.Equal(0, document.IndexOf(paragraph));
        }
Esempio n. 7
0
        public void TestElementAt()
        {
            var document  = new MarkdownDocument();
            var paragraph = new MarkdownParagraph("");

            document.Append(paragraph);

            Assert.Equal(paragraph, document.ElementAt(0));
        }
Esempio n. 8
0
 internal static void DotNetCommentsFillParagraph(MarkdownParagraph paragraph, DotNetComment comment, DotNetMember parent = null)
 {
     if (comment is DotNetCommentQualifiedLinkedGroup && (comment.Tag == CommentTag.See || comment.Tag == CommentTag.SeeAlso))
     {
         paragraph.Add(ToMDLink(comment as DotNetCommentQualifiedLinkedGroup, parent));
     }
     else if (comment is DotNetCommentGroup)
     {
         paragraph.Add(DotNetCommentGroupToMarkdown(comment as DotNetCommentGroup, parent));
     }
     else if (comment is DotNetCommentCodeBlock)
     {
         paragraph.Add(new MarkdownCodeBlock((comment as DotNetCommentCodeBlock).Text, (comment as DotNetCommentCodeBlock).Language));
     }
     else if (comment is DotNetCommentCode)
     {
         paragraph.Add(new MarkdownCode((comment as DotNetCommentCode).Text));
     }
     else if (comment is DotNetCommentText)
     {
         string text = (comment as DotNetCommentText).Text;
         if (String.IsNullOrEmpty(text))
         {
             return;
         }
         string[] lines = text.Split('\n');
         if (lines.Length == 0)
         {
             return;
         }
         for (int i = 0; i < lines.Length - 1; i++)
         {
             paragraph.Add(new MarkdownLine(lines[i]));
         }
         if (!String.IsNullOrEmpty(lines.Last()))
         {
             paragraph.Add(new MarkdownText(lines.Last()));
         }
     }
     else if (comment is DotNetCommentList)
     {
         paragraph.Add(ToMDList(comment as DotNetCommentList, parent));
     }
     else if (comment is DotNetCommentTable)
     {
         paragraph.Add(ToMDTable(comment as DotNetCommentTable));
     }
     else if (comment is DotNetCommentQualifiedLink)
     {
         paragraph.Add(ToMDLink(comment as DotNetCommentQualifiedLink, parent));
     }
     else if (comment is DotNetCommentParameterLink)            //paramref and typeparamref
     {
         paragraph.Add(ToMDText(comment as DotNetCommentParameterLink));
     }
 }
        public void Create_WithTitleTestValue_ShouldSetValue()
        {
            Mock <IPrintableMarkdownElementFactory> markdownElementFactory =
                new Mock <IPrintableMarkdownElementFactory>();

            MarkdownParagraph document = new MarkdownParagraph("Title",
                                                               markdownElementFactory.Object);

            Assert.AreEqual("Title", document.Title);
        }
        public void HeaderContent_FromInitializedObject_ShouldValueFromObjectTitle()
        {
            Mock <IPrintableMarkdownElementFactory> markdownElementFactory =
                new Mock <IPrintableMarkdownElementFactory>();

            MarkdownParagraph document = new MarkdownParagraph("Title",
                                                               markdownElementFactory.Object);

            Assert.AreEqual("Title", document.HeaderContent);
        }
        public void Print_WithTitleTestValue_ShouldReturnExpectedMarkdownFormat()
        {
            Mock <IPrintableMarkdownElementFactory> markdownElementFactory =
                new Mock <IPrintableMarkdownElementFactory>();

            MarkdownParagraph document = new MarkdownParagraph("Title",
                                                               markdownElementFactory.Object);

            Assert.AreEqual("# Title", document.Print());
        }
Esempio n. 12
0
        public void TestRemoveElement()
        {
            var document  = new MarkdownDocument();
            var paragraph = new MarkdownParagraph("");

            document.Append(paragraph);

            document.Remove(paragraph);

            Assert.Equal(0, document.Length);
        }
Esempio n. 13
0
    public static Span FindParagraph(string src, MarkdownParagraph mdp)
    {
        var mdwords    = Paragraph2Words(mdp).ToList();
        var mdwords2   = string.Join(",", mdwords);
        var paragraphs = from paragraph in FindParagraphs(src)
                         let pwords                 = String2Words(paragraph.text)
                                              let i = LevenshteinDistance(mdwords, pwords)
                                                      orderby i ascending
                                                      select paragraph.span;

        return(paragraphs.FirstOrDefault());
    }
        public void AddNewContent_FromInterfaceIPrintableParagraphTable_CallMatchingMethodOnElementFactory()
        {
            Mock <IPrintableMarkdownElementFactory> markdownElementFactory =
                new Mock <IPrintableMarkdownElementFactory>();

            MarkdownParagraph document = new MarkdownParagraph("Title",
                                                               markdownElementFactory.Object);

            document.AddNewContent <IPrintableParagraphTable>();

            markdownElementFactory.Verify(ef => ef.CreateElement <IPrintableParagraphTable>(), Times.Exactly(1));
        }
Esempio n. 15
0
        public void TestReplace()
        {
            var document  = new MarkdownDocument();
            var paragraph = new MarkdownParagraph("");

            document.Append(paragraph);

            var code = new MarkdownCode("text", "");

            document.Replace(paragraph, code);

            Assert.Equal(code, document.ElementAt(0));
        }
        public void MarkdownParagraph_Nested()
        {
            //arrange
            MarkdownParagraph p1        = new MarkdownParagraph("The Quick Brown Fox");
            MarkdownParagraph p2        = new MarkdownParagraph(new MarkdownLine("Jumped Over"));
            MarkdownParagraph p3        = new MarkdownParagraph("The Lazy Dog    \n\t  \n\n");
            MarkdownParagraph paragraph = new MarkdownParagraph(p1, p2, p3);
            //act
            string result = paragraph.ToMarkdownString(null);

            //assert
            Assert.AreEqual("The Quick Brown Fox  \n\nJumped Over  \n\nThe Lazy Dog  \n\n", result);
        }
        public void Print_WithThreePrintableContentItems_ShouldCallPrintForEachItem()
        {
            Mock <IPrintableMarkdownElementFactory> markdownElementFactory =
                new Mock <IPrintableMarkdownElementFactory>();

            Mock <IPrintable> printableMock = new Mock <IPrintable>();

            MarkdownParagraph document = new MarkdownParagraph("Title",
                                                               markdownElementFactory.Object);

            document.Content.Add(printableMock.Object);
            document.Content.Add(printableMock.Object);
            document.Content.Add(printableMock.Object);

            document.Print();

            printableMock.Verify(pm => pm.Print(), Times.Exactly(3));
        }
Esempio n. 18
0
 internal static IMarkdownInSection DotNetCommentGroupToMarkdown(DotNetCommentGroup group, DotNetMember parent = null)
 {
     if (group.Tag == CommentTag.See || group.Tag == CommentTag.SeeAlso)
     {
         MarkdownLine line = new MarkdownLine();
         foreach (DotNetComment comment in group.Comments)
         {
             line.Concat(DotNetCommentsToLine(comment, parent));
         }
         return(line);
     }
     else
     {
         MarkdownParagraph paragraph = new MarkdownParagraph();
         foreach (DotNetComment comment in group.Comments)
         {
             DotNetCommentsFillParagraph(paragraph, comment, parent);
         }
         return(paragraph);
     }
 }
Esempio n. 19
0
 private static IEnumerable <string> Paragraph2Words(MarkdownParagraph md)
 {
     if (md.IsHeading)
     {
         var mdh = md as MarkdownParagraph.Heading;
         foreach (var s in Spans2Words(mdh.body))
         {
             yield return(s);
         }
     }
     else if (md.IsParagraph)
     {
         var mdp = md as MarkdownParagraph.Paragraph;
         foreach (var s in Spans2Words(mdp.body))
         {
             yield return(s);
         }
     }
     else if (md.IsListBlock)
     {
         var mdl = md as MarkdownParagraph.ListBlock;
         foreach (var bullet in mdl.items)
         {
             foreach (var s in Paragraphs2Words(bullet))
             {
                 yield return(s);
             }
         }
     }
     else if (md.IsCodeBlock)
     {
         var mdc  = md as MarkdownParagraph.CodeBlock;
         var code = mdc.code;
         var lang = mdc.language?.Trim();
         if (!string.IsNullOrWhiteSpace(lang))
         {
             yield return(lang);
         }
         foreach (var s in String2Words(code))
         {
             yield return(s);
         }
     }
     else if (md.IsTableBlock)
     {
         var mdt    = md as MarkdownParagraph.TableBlock;
         var header = mdt.headers.Option();
         var align  = mdt.alignments;
         var rows   = mdt.rows;
         foreach (var col in header)
         {
             foreach (var s in Paragraphs2Words(col))
             {
                 yield return(s);
             }
         }
         foreach (var row in rows)
         {
             foreach (var col in row)
             {
                 foreach (var s in Paragraphs2Words(col))
                 {
                     yield return(s);
                 }
             }
         }
     }
     else if (md.IsEmbedParagraphs)
     {
     }
     else if (md.IsHorizontalRule)
     {
     }
     else if (md.IsInlineBlock)
     {
         var mdi = md as MarkdownParagraph.InlineBlock;
         foreach (var s in String2Words(mdi.code))
         {
             yield return(s);
         }
     }
     else if (md.IsLatexBlock)
     {
         var mdl = md as MarkdownParagraph.LatexBlock;
         foreach (var str in mdl.body)
         {
             foreach (var s in String2Words(str))
             {
                 yield return(s);
             }
         }
     }
     else if (md.IsQuotedBlock)
     {
         var mdq = md as MarkdownParagraph.QuotedBlock;
         foreach (var s in Paragraphs2Words(mdq.paragraphs))
         {
             yield return(s);
         }
     }
     else if (md.IsSpan)
     {
         var mds = md as MarkdownParagraph.Span;
         foreach (var s in Spans2Words(mds.body))
         {
             yield return(s);
         }
     }
 }
Esempio n. 20
0
        IEnumerable <OpenXmlCompositeElement> Paragraph2Paragraphs(MarkdownParagraph md)
        {
            reporter.CurrentParagraph = md;
            if (md.IsHeading)
            {
                var mdh   = md as MarkdownParagraph.Heading;
                var level = mdh.size;
                var spans = mdh.body;
                var sr    = sections[new SectionRef(mdh, filename).Url];
                reporter.CurrentSection = sr;
                var properties = new List <OpenXmlElement>
                {
                    new ParagraphStyleId {
                        Val = $"Heading{level}"
                    }
                };
                if (sr.Number is null)
                {
                    properties.Add(new NumberingProperties(new NumberingLevelReference {
                        Val = 0
                    }, new NumberingId {
                        Val = 0
                    }));
                }
                var props = new ParagraphProperties(properties);
                var p     = new Paragraph {
                    ParagraphProperties = props
                };
                context.MaxBookmarkId.Value += 1;
                p.AppendChild(new BookmarkStart {
                    Name = sr.BookmarkName, Id = context.MaxBookmarkId.Value.ToString()
                });
                p.Append(Span2Elements(MarkdownSpan.NewLiteral(sr.TitleWithoutNumber, FSharpOption <MarkdownRange> .None)));
                p.AppendChild(new BookmarkEnd {
                    Id = context.MaxBookmarkId.Value.ToString()
                });
                yield return(p);

                var    i = sr.Url.IndexOf("#");
                string currentSection = $"{sr.Url.Substring(0, i)} {new string('#', level)} {sr.Title} [{sr.Number}]";
                reporter.Log(currentSection);
                yield break;
            }

            else if (md.IsParagraph)
            {
                var mdp   = md as MarkdownParagraph.Paragraph;
                var spans = mdp.body;
                yield return(new Paragraph(Spans2Elements(spans)));

                yield break;
            }

            else if (md.IsQuotedBlock)
            {
                var mdq = md as MarkdownParagraph.QuotedBlock;
                // TODO: Actually make this a block quote.
                // See https://github.com/ECMA-TC49-TG2/conversion-to-markdown/issues/123
                foreach (var paragraph in mdq.paragraphs.SelectMany(Paragraph2Paragraphs))
                {
                    yield return(paragraph);
                }
                yield break;
            }

            else if (md.IsListBlock)
            {
                var mdl  = md as MarkdownParagraph.ListBlock;
                var flat = FlattenList(mdl);

                // Let's figure out what kind of list it is - ordered or unordered? nested?
                var format0 = new[] { "1", "1", "1", "1" };
                foreach (var item in flat)
                {
                    format0[item.Level] = (item.IsBulletOrdered ? "1" : "o");
                }

                var format = string.Join("", format0);

                var numberingPart = wordDocument.MainDocumentPart.NumberingDefinitionsPart ?? wordDocument.MainDocumentPart.AddNewPart <NumberingDefinitionsPart>("NumberingDefinitionsPart001");
                if (numberingPart.Numbering == null)
                {
                    numberingPart.Numbering = new Numbering();
                }

                Func <int, bool, Level> createLevel;
                createLevel = (level, isOrdered) =>
                {
                    var numformat = NumberFormatValues.Bullet;
                    var levelText = new[] { "·", "o", "·", "o" }[level];
                    if (isOrdered && level == 0)
                    {
                        numformat = NumberFormatValues.Decimal; levelText = "%1.";
                    }
                    if (isOrdered && level == 1)
                    {
                        numformat = NumberFormatValues.LowerLetter; levelText = "%2.";
                    }
                    if (isOrdered && level == 2)
                    {
                        numformat = NumberFormatValues.LowerRoman; levelText = "%3.";
                    }
                    if (isOrdered && level == 3)
                    {
                        numformat = NumberFormatValues.LowerRoman; levelText = "%4.";
                    }
                    var r = new Level {
                        LevelIndex = level
                    };
                    r.Append(new StartNumberingValue {
                        Val = 1
                    });
                    r.Append(new NumberingFormat {
                        Val = numformat
                    });
                    r.Append(new LevelText {
                        Val = levelText
                    });
                    r.Append(new ParagraphProperties(new Indentation {
                        Left = (540 + 360 * level).ToString(), Hanging = "360"
                    }));
                    if (levelText == "·")
                    {
                        r.Append(new NumberingSymbolRunProperties(new RunFonts {
                            Hint = FontTypeHintValues.Default, Ascii = "Symbol", HighAnsi = "Symbol", EastAsia = "Times new Roman", ComplexScript = "Times new Roman"
                        }));
                    }

                    if (levelText == "o")
                    {
                        r.Append(new NumberingSymbolRunProperties(new RunFonts {
                            Hint = FontTypeHintValues.Default, Ascii = "Courier New", HighAnsi = "Courier New", ComplexScript = "Courier New"
                        }));
                    }

                    return(r);
                };
                var level0 = createLevel(0, format[0] == '1');
                var level1 = createLevel(1, format[1] == '1');
                var level2 = createLevel(2, format[2] == '1');
                var level3 = createLevel(3, format[3] == '1');

                var abstracts = numberingPart.Numbering.OfType <AbstractNum>().Select(an => an.AbstractNumberId.Value).ToList();
                var aid       = (abstracts.Count == 0 ? 1 : abstracts.Max() + 1);
                var aabstract = new AbstractNum(new MultiLevelType()
                {
                    Val = MultiLevelValues.Multilevel
                }, level0, level1, level2, level3)
                {
                    AbstractNumberId = aid
                };
                numberingPart.Numbering.InsertAt(aabstract, 0);

                var instances   = numberingPart.Numbering.OfType <NumberingInstance>().Select(ni => ni.NumberID.Value);
                var nid         = (instances.Count() == 0 ? 1 : instances.Max() + 1);
                var numInstance = new NumberingInstance(new AbstractNumId {
                    Val = aid
                })
                {
                    NumberID = nid
                };
                numberingPart.Numbering.AppendChild(numInstance);

                // We'll also figure out the indentation(for the benefit of those paragraphs that should be
                // indendent with the list but aren't numbered). I'm not sure what the indent comes from.
                // in the docx, each AbstractNum that I created has an indent for each of its levels,
                // defaulted at 900, 1260, 1620, ... but I can't see where in the above code that's created?
                Func <int, string> calcIndent = level => (540 + level * 360).ToString();

                foreach (var item in flat)
                {
                    var content = item.Paragraph;
                    if (content.IsParagraph || content.IsSpan)
                    {
                        var spans = (content.IsParagraph ? (content as MarkdownParagraph.Paragraph).body : (content as MarkdownParagraph.Span).body);
                        if (item.HasBullet)
                        {
                            yield return(new Paragraph(Spans2Elements(spans))
                            {
                                ParagraphProperties = new ParagraphProperties(new NumberingProperties(new ParagraphStyleId {
                                    Val = "ListParagraph"
                                }, new NumberingLevelReference {
                                    Val = item.Level
                                }, new NumberingId {
                                    Val = nid
                                }))
                            });
                        }
                        else
                        {
                            yield return(new Paragraph(Spans2Elements(spans))
                            {
                                ParagraphProperties = new ParagraphProperties(new Indentation {
                                    Left = calcIndent(item.Level)
                                })
                            });
                        }
                    }
                    else if (content.IsQuotedBlock || content.IsCodeBlock)
                    {
                        foreach (var p in Paragraph2Paragraphs(content))
                        {
                            var props = p.GetFirstChild <ParagraphProperties>();
                            if (props == null)
                            {
                                props = new ParagraphProperties();
                                p.InsertAt(props, 0);
                            }
                            var indent = props?.GetFirstChild <Indentation>();
                            if (indent == null)
                            {
                                indent = new Indentation();
                                props.Append(indent);
                            }
                            indent.Left = calcIndent(item.Level);
                            yield return(p);
                        }
                    }
                    else if (content.IsTableBlock)
                    {
                        foreach (var p in Paragraph2Paragraphs(content))
                        {
                            var table = p as Table;
                            if (table == null)
                            {
                                yield return(p);

                                continue;
                            }
                            var tprops  = table.GetFirstChild <TableProperties>();
                            var tindent = tprops?.GetFirstChild <TableIndentation>();
                            if (tindent == null)
                            {
                                throw new Exception("Ooops! Table is missing indentation");
                            }

                            tindent.Width = int.Parse(calcIndent(item.Level));
                            yield return(table);
                        }
                    }
                    else
                    {
                        reporter.Error("MD08", $"Unexpected item in list '{content.GetType().Name}'");
                    }
                }
            }

            else if (md.IsCodeBlock)
            {
                var mdc  = md as MarkdownParagraph.CodeBlock;
                var code = mdc.code;
                var lang = mdc.language;
                code = BugWorkaroundDecode(code);
                var runs        = new List <Run>();
                var onFirstLine = true;
                IEnumerable <ColorizedLine> lines;
                switch (lang)
                {
                case "csharp":
                case "c#":
                case "cs":
                    lines = Colorize.CSharp(code);
                    break;

                case "vb":
                case "vbnet":
                case "vb.net":
                    lines = Colorize.VB(code);
                    break;

                case "":
                case "console":
                case "xml":
                    lines = Colorize.PlainText(code);
                    break;

                case "ANTLR":
                case "antlr":
                    lines = Antlr.ColorizeAntlr(code);
                    break;

                default:
                    reporter.Error("MD09", $"unrecognized language {lang}");
                    lines = Colorize.PlainText(code);
                    break;
                }

                foreach (var line in lines)
                {
                    if (onFirstLine)
                    {
                        onFirstLine = false;
                    }
                    else
                    {
                        runs.Add(new Run(new Break()));
                    }

                    foreach (var word in line.Words)
                    {
                        var run   = new Run();
                        var props = new RunProperties();
                        if (word.Red != 0 || word.Green != 0 || word.Blue != 0)
                        {
                            props.Append(new Color {
                                Val = $"{word.Red:X2}{word.Green:X2}{word.Blue:X2}"
                            });
                        }

                        if (word.IsItalic)
                        {
                            props.Append(new Italic());
                        }

                        if (props.HasChildren)
                        {
                            run.Append(props);
                        }

                        run.Append(new Text(word.Text)
                        {
                            Space = SpaceProcessingModeValues.Preserve
                        });
                        runs.Add(run);
                    }
                }
                if (lang == "antlr")
                {
                    var p = new Paragraph()
                    {
                        ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                            Val = "Grammar"
                        })
                    };
                    var prodref = productions.Single(prod => prod.Code == code);
                    context.MaxBookmarkId.Value += 1;
                    p.AppendChild(new BookmarkStart {
                        Name = prodref.BookmarkName, Id = context.MaxBookmarkId.Value.ToString()
                    });
                    p.Append(runs);
                    p.AppendChild(new BookmarkEnd {
                        Id = context.MaxBookmarkId.Value.ToString()
                    });
                    yield return(p);
                }
                else
                {
                    var p = new Paragraph()
                    {
                        ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                            Val = "Code"
                        })
                    };
                    p.Append(runs);
                    yield return(p);
                }
            }

            else if (md.IsTableBlock)
            {
                var mdt    = md as MarkdownParagraph.TableBlock;
                var header = mdt.headers.Option();
                var align  = mdt.alignments;
                var rows   = mdt.rows;
                var table  = new Table();
                if (header == null)
                {
                    reporter.Error("MD10", "Github requires all tables to have header rows");
                }

                if (!header.Any(cell => cell.Length > 0))
                {
                    header = null; // even if Github requires an empty header, we can at least cull it from Docx
                }

                var tstyle = new TableStyle {
                    Val = "TableGrid"
                };
                var tindent = new TableIndentation {
                    Width = 360, Type = TableWidthUnitValues.Dxa
                };
                var tborders = new TableBorders();
                tborders.TopBorder = new TopBorder {
                    Val = BorderValues.Single
                };
                tborders.BottomBorder = new BottomBorder {
                    Val = BorderValues.Single
                };
                tborders.LeftBorder = new LeftBorder {
                    Val = BorderValues.Single
                };
                tborders.RightBorder = new RightBorder {
                    Val = BorderValues.Single
                };
                tborders.InsideHorizontalBorder = new InsideHorizontalBorder {
                    Val = BorderValues.Single
                };
                tborders.InsideVerticalBorder = new InsideVerticalBorder {
                    Val = BorderValues.Single
                };
                var tcellmar = new TableCellMarginDefault();
                tcellmar.Append();
                table.Append(new TableProperties(tstyle, tindent, tborders));
                var ncols = align.Length;
                for (int irow = -1; irow < rows.Length; irow++)
                {
                    if (irow == -1 && header == null)
                    {
                        continue;
                    }

                    var mdrow = (irow == -1 ? header : rows[irow]);
                    var row   = new TableRow();
                    for (int icol = 0; icol < Math.Min(ncols, mdrow.Length); icol++)
                    {
                        var mdcell = mdrow[icol];
                        var cell   = new TableCell();
                        var pars   = Paragraphs2Paragraphs(mdcell).ToList();
                        for (int ip = 0; ip < pars.Count; ip++)
                        {
                            var p = pars[ip] as Paragraph;
                            if (p == null)
                            {
                                cell.Append(pars[ip]);
                                continue;
                            }
                            var props = new ParagraphProperties(new ParagraphStyleId {
                                Val = "TableCellNormal"
                            });
                            if (align[icol].IsAlignCenter)
                            {
                                props.Append(new Justification {
                                    Val = JustificationValues.Center
                                });
                            }

                            if (align[icol].IsAlignRight)
                            {
                                props.Append(new Justification {
                                    Val = JustificationValues.Right
                                });
                            }

                            p.InsertAt(props, 0);
                            cell.Append(pars[ip]);
                        }
                        if (pars.Count == 0)
                        {
                            cell.Append(new Paragraph(new ParagraphProperties(new SpacingBetweenLines {
                                After = "0"
                            }), new Run(new Text(""))));
                        }

                        row.Append(cell);
                    }
                    table.Append(row);
                }
                yield return(new Paragraph(new Run(new Text("")))
                {
                    ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                        Val = "TableLineBefore"
                    })
                });

                yield return(table);

                yield return(new Paragraph(new Run(new Text("")))
                {
                    ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                        Val = "TableLineAfter"
                    })
                });
            }
            else
            {
                reporter.Error("MD11", $"Unrecognized markdown element {md.GetType().Name}");
                yield return(new Paragraph(new Run(new Text($"[{md.GetType().Name}]"))));
            }
        }
Esempio n. 21
0
        IEnumerable <OpenXmlCompositeElement> Paragraph2Paragraphs(MarkdownParagraph md)
        {
            if (md.IsHeading)
            {
                var mdh   = md as MarkdownParagraph.Heading;
                var level = mdh.Item1;
                var spans = mdh.Item2;
                var sr    = sections[new SectionRef(mdh, filename).Url];
                var props = new ParagraphProperties(new ParagraphStyleId()
                {
                    Val = $"Heading{level}"
                });
                var p = new Paragraph {
                    ParagraphProperties = props
                };
                maxBookmarkId.Value += 1;
                p.AppendChild(new BookmarkStart {
                    Name = sr.BookmarkName, Id = maxBookmarkId.Value.ToString()
                });
                p.Append(Spans2Elements(spans));
                p.AppendChild(new BookmarkEnd {
                    Id = maxBookmarkId.Value.ToString()
                });
                yield return(p);

                Console.WriteLine(new string(' ', level * 4 - 4) + sr.Number + " " + sr.Title);
                yield break;
            }

            else if (md.IsParagraph)
            {
                var mdp   = md as MarkdownParagraph.Paragraph;
                var spans = mdp.Item;
                yield return(new Paragraph(Spans2Elements(spans)));

                yield break;
            }

            else if (md.IsListBlock)
            {
                var mdl  = md as MarkdownParagraph.ListBlock;
                var flat = FlattenList(mdl);

                // Let's figure out what kind of list it is - ordered or unordered? nested?
                var format0 = new[] { "1", "1", "1", "1" };
                foreach (var item in flat)
                {
                    format0[item.Level] = (item.IsBulletOrdered ? "1" : "o");
                }
                var format = string.Join("", format0);

                var numberingPart = wdoc.MainDocumentPart.NumberingDefinitionsPart ?? wdoc.MainDocumentPart.AddNewPart <NumberingDefinitionsPart>("NumberingDefinitionsPart001");
                if (numberingPart.Numbering == null)
                {
                    numberingPart.Numbering = new Numbering();
                }

                Func <int, bool, Level> createLevel;
                createLevel = (level, isOrdered) =>
                {
                    var numformat = NumberFormatValues.Bullet;
                    var levelText = new[] { "·", "o", "·", "o" }[level];
                    if (isOrdered && level == 0)
                    {
                        numformat = NumberFormatValues.Decimal; levelText = "%1.";
                    }
                    if (isOrdered && level == 1)
                    {
                        numformat = NumberFormatValues.LowerLetter; levelText = "%2.";
                    }
                    if (isOrdered && level == 2)
                    {
                        numformat = NumberFormatValues.LowerRoman; levelText = "%3.";
                    }
                    if (isOrdered && level == 3)
                    {
                        numformat = NumberFormatValues.LowerRoman; levelText = "%4.";
                    }
                    var r = new Level {
                        LevelIndex = level
                    };
                    r.Append(new StartNumberingValue {
                        Val = 1
                    });
                    r.Append(new NumberingFormat {
                        Val = numformat
                    });
                    r.Append(new LevelText {
                        Val = levelText
                    });
                    r.Append(new ParagraphProperties(new Indentation {
                        Left = (540 + 360 * level).ToString(), Hanging = "360"
                    }));
                    if (levelText == "·")
                    {
                        r.Append(new NumberingSymbolRunProperties(new RunFonts {
                            Hint = FontTypeHintValues.Default, Ascii = "Symbol", HighAnsi = "Symbol", EastAsia = "Times new Roman", ComplexScript = "Times new Roman"
                        }));
                    }
                    if (levelText == "o")
                    {
                        r.Append(new NumberingSymbolRunProperties(new RunFonts {
                            Hint = FontTypeHintValues.Default, Ascii = "Courier New", HighAnsi = "Courier New", ComplexScript = "Courier New"
                        }));
                    }
                    return(r);
                };
                var level0 = createLevel(0, format[0] == '1');
                var level1 = createLevel(1, format[1] == '1');
                var level2 = createLevel(2, format[2] == '1');
                var level3 = createLevel(3, format[3] == '1');

                var abstracts = numberingPart.Numbering.OfType <AbstractNum>().Select(an => an.AbstractNumberId.Value).ToList();
                var aid       = (abstracts.Count == 0 ? 1 : abstracts.Max() + 1);
                var aabstract = new AbstractNum(new MultiLevelType()
                {
                    Val = MultiLevelValues.Multilevel
                }, level0, level1, level2, level3)
                {
                    AbstractNumberId = aid
                };
                numberingPart.Numbering.InsertAt(aabstract, 0);

                var instances   = numberingPart.Numbering.OfType <NumberingInstance>().Select(ni => ni.NumberID.Value);
                var nid         = (instances.Count() == 0 ? 1 : instances.Max() + 1);
                var numInstance = new NumberingInstance(new AbstractNumId {
                    Val = aid
                })
                {
                    NumberID = nid
                };
                numberingPart.Numbering.AppendChild(numInstance);

                // We'll also figure out the indentation(for the benefit of those paragraphs that should be
                // indendent with the list but aren't numbered). I'm not sure what the indent comes from.
                // in the docx, each AbstractNum that I created has an indent for each of its levels,
                // defaulted at 900, 1260, 1620, ... but I can't see where in the above code that's created?
                Func <int, string> calcIndent = level => (540 + level * 360).ToString();

                foreach (var item in flat)
                {
                    var content = item.Paragraph;
                    if (content.IsParagraph || content.IsSpan)
                    {
                        var spans = (content.IsParagraph ? (content as MarkdownParagraph.Paragraph).Item : (content as MarkdownParagraph.Span).Item);
                        if (item.HasBullet)
                        {
                            yield return new Paragraph(Spans2Elements(spans))
                                   {
                                       ParagraphProperties = new ParagraphProperties(new NumberingProperties(new ParagraphStyleId {
                                    Val = "ListParagraph"
                                }, new NumberingLevelReference {
                                    Val = item.Level
                                }, new NumberingId {
                                    Val = nid
                                }))
                                   }
                        }
                        ;
                        else
                        {
                            yield return new Paragraph(Spans2Elements(spans))
                                   {
                                       ParagraphProperties = new ParagraphProperties(new Indentation {
                                    Left = calcIndent(item.Level)
                                })
                                   }
                        };
                    }
                    else if (content.IsQuotedBlock || content.IsCodeBlock)
                    {
                        foreach (var p in Paragraph2Paragraphs(content))
                        {
                            var props = p.GetFirstChild <ParagraphProperties>();

                            if (props == null)
                            {
                                props = new ParagraphProperties(); p.InsertAt(props, 0);
                            }
                            var indent = props?.GetFirstChild <Indentation>();
                            if (indent == null)
                            {
                                indent = new Indentation(); props.Append(indent);
                            }
                            indent.Left = calcIndent(item.Level);
                            yield return(p);
                        }
                    }
                    else if (content.IsTableBlock)
                    {
                        foreach (var p in Paragraph2Paragraphs(content))
                        {
                            var table = p as Table;
                            if (table == null)
                            {
                                yield return(p); continue;
                            }
                            var tprops  = table.GetFirstChild <TableProperties>();
                            var tindent = tprops?.GetFirstChild <TableIndentation>();
                            if (tindent == null)
                            {
                                throw new Exception("Ooops! Table is missing indentation");
                            }
                            tindent.Width = int.Parse(calcIndent(item.Level));
                            yield return(table);
                        }
                    }
                    else
                    {
                        throw new Exception("Unexpected item in list");
                    }
                }
            }

            else if (md.IsCodeBlock)
            {
                var mdc  = md as MarkdownParagraph.CodeBlock;
                var code = mdc.Item1;
                var lang = mdc.Item2;
                code = BugWorkaroundDecode(code);
                var runs        = new List <Run>();
                var onFirstLine = true;
                IEnumerable <ColorizedLine> lines;
                if (lang == "csharp" || lang == "c#" || lang == "cs")
                {
                    lines = Colorize.CSharp(code);
                }
                else if (lang == "vb" || lang == "vbnet" || lang == "vb.net")
                {
                    lines = Colorize.VB(code);
                }
                else if (lang == "" || lang == "xml")
                {
                    lines = Colorize.PlainText(code);
                }
                else if (lang == "antlr")
                {
                    lines = Antlr.ColorizeAntlr(code);
                }
                else
                {
                    throw new NotSupportedException($"unrecognized language {lang}");
                }
                foreach (var line in lines)
                {
                    if (onFirstLine)
                    {
                        onFirstLine = false;
                    }
                    else
                    {
                        runs.Add(new Run(new Break()));
                    }
                    foreach (var word in line.Words)
                    {
                        var run   = new Run();
                        var props = new RunProperties();
                        if (word.Red != 0 || word.Green != 0 || word.Blue != 0)
                        {
                            props.Append(new Color {
                                Val = $"{word.Red:X2}{word.Green:X2}{word.Blue:X2}"
                            });
                        }
                        if (word.IsItalic)
                        {
                            props.Append(new Italic());
                        }
                        if (props.HasChildren)
                        {
                            run.Append(props);
                        }
                        run.Append(new Text(word.Text)
                        {
                            Space = SpaceProcessingModeValues.Preserve
                        });
                        runs.Add(run);
                    }
                }
                var style = new ParagraphStyleId {
                    Val = (lang == "antlr" ? "Grammar" : "Code")
                };
                yield return(new Paragraph(runs)
                {
                    ParagraphProperties = new ParagraphProperties(style)
                });
            }

            else if (md.IsQuotedBlock)
            {
                var mdq     = md as MarkdownParagraph.QuotedBlock;
                var quoteds = mdq.Item;
                var kind    = "";
                foreach (var quoted0 in quoteds)
                {
                    var quoted = quoted0;
                    if (quoted.IsParagraph)
                    {
                        var p     = quoted as MarkdownParagraph.Paragraph;
                        var spans = p.Item;
                        if (spans.Any() && spans.First().IsStrong)
                        {
                            var strong = (spans.First() as MarkdownSpan.Strong).Item;
                            if (strong.Any() && strong.First().IsLiteral)
                            {
                                var literal = mdunescape(strong.First() as MarkdownSpan.Literal);
                                if (literal == "Note")
                                {
                                    kind = "AlertText";
                                }
                                else if (literal == "Annotation")
                                {
                                    kind = "Annotation";
                                    yield return(new Paragraph(Span2Elements(spans.Head))
                                    {
                                        ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                                            Val = kind
                                        })
                                    });

                                    if (spans.Tail.Any() && spans.Tail.First().IsLiteral)
                                    {
                                        quoted = MarkdownParagraph.NewParagraph(new Microsoft.FSharp.Collections.FSharpList <MarkdownSpan>(MarkdownSpan.NewLiteral(mdunescape(spans.Tail.First() as MarkdownSpan.Literal).TrimStart()), spans.Tail.Tail));
                                    }
                                    else
                                    {
                                        quoted = MarkdownParagraph.NewParagraph(spans.Tail);
                                    }
                                }
                            }
                        }
                        //
                        foreach (var qp in Paragraph2Paragraphs(quoted))
                        {
                            var qpp = qp as Paragraph;
                            if (qpp != null)
                            {
                                var props = new ParagraphProperties(new ParagraphStyleId()
                                {
                                    Val = kind
                                }); qpp.ParagraphProperties = props;
                            }
                            yield return(qp);
                        }
                    }

                    else if (quoted.IsCodeBlock)
                    {
                        var mdc              = quoted as MarkdownParagraph.CodeBlock;
                        var code             = mdc.Item1;
                        var lang             = mdc.Item2;
                        var ignoredAfterLang = mdc.Item3;
                        var lines            = code.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).ToList();
                        if (string.IsNullOrWhiteSpace(lines.Last()))
                        {
                            lines.RemoveAt(lines.Count - 1);
                        }
                        var run = new Run()
                        {
                            RunProperties = new RunProperties(new RunStyle {
                                Val = "CodeEmbedded"
                            })
                        };
                        foreach (var line in lines)
                        {
                            if (run.ChildElements.Count() > 1)
                            {
                                run.Append(new Break());
                            }
                            run.Append(new Text("    " + line)
                            {
                                Space = SpaceProcessingModeValues.Preserve
                            });
                        }
                        yield return(new Paragraph(run)
                        {
                            ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                                Val = kind
                            })
                        });
                    }

                    else if (quoted.IsListBlock)
                    {
                        if (!(quoted as MarkdownParagraph.ListBlock).Item1.IsOrdered)
                        {
                            throw new NotImplementedException("unordered list inside annotation");
                        }
                        var count = 1;
                        foreach (var qp in Paragraph2Paragraphs(quoted))
                        {
                            var qpp = qp as Paragraph;
                            if (qpp == null)
                            {
                                yield return(qp); continue;
                            }
                            qp.InsertAt(new Run(new Text($"{count}. ")
                            {
                                Space = SpaceProcessingModeValues.Preserve
                            }), 0);
                            count += 1;
                            var props = new ParagraphProperties(new ParagraphStyleId()
                            {
                                Val = kind
                            });
                            qpp.ParagraphProperties = props;
                            yield return(qp);
                        }
                    }
                }
            }

            else if (md.IsTableBlock)
            {
                var mdt    = md as MarkdownParagraph.TableBlock;
                var header = mdt.Item1.Option();
                var align  = mdt.Item2;
                var rows   = mdt.Item3;
                var table  = new Table();
                var tstyle = new TableStyle {
                    Val = "TableGrid"
                };
                var tindent = new TableIndentation {
                    Width = 360, Type = TableWidthUnitValues.Dxa
                };
                var tborders = new TableBorders();
                tborders.TopBorder = new TopBorder {
                    Val = BorderValues.Single
                };
                tborders.BottomBorder = new BottomBorder {
                    Val = BorderValues.Single
                };
                tborders.LeftBorder = new LeftBorder {
                    Val = BorderValues.Single
                };
                tborders.RightBorder = new RightBorder {
                    Val = BorderValues.Single
                };
                tborders.InsideHorizontalBorder = new InsideHorizontalBorder {
                    Val = BorderValues.Single
                };
                tborders.InsideVerticalBorder = new InsideVerticalBorder {
                    Val = BorderValues.Single
                };
                var tcellmar = new TableCellMarginDefault();
                tcellmar.Append();
                table.Append(new TableProperties(tstyle, tindent, tborders));
                var ncols = align.Length;
                for (int irow = -1; irow < rows.Length; irow++)
                {
                    if (irow == -1 && header == null)
                    {
                        continue;
                    }
                    var mdrow = (irow == -1 ? header : rows[irow]);
                    var row   = new TableRow();
                    for (int icol = 0; icol < Math.Min(ncols, mdrow.Length); icol++)
                    {
                        var mdcell = mdrow[icol];
                        var cell   = new TableCell();
                        var pars   = Paragraphs2Paragraphs(mdcell).ToList();
                        for (int ip = 0; ip < pars.Count; ip++)
                        {
                            var p = pars[ip] as Paragraph;
                            if (p == null)
                            {
                                cell.Append(pars[ip]); continue;
                            }
                            var props = new ParagraphProperties(new ParagraphStyleId {
                                Val = "TableCellNormal"
                            });
                            if (align[icol].IsAlignCenter)
                            {
                                props.Append(new Justification {
                                    Val = JustificationValues.Center
                                });
                            }
                            if (align[icol].IsAlignRight)
                            {
                                props.Append(new Justification {
                                    Val = JustificationValues.Right
                                });
                            }
                            p.InsertAt(props, 0);
                            cell.Append(pars[ip]);
                        }
                        if (pars.Count == 0)
                        {
                            cell.Append(new Paragraph(new ParagraphProperties(new SpacingBetweenLines {
                                After = "0"
                            }), new Run(new Text(""))));
                        }
                        row.Append(cell);
                    }
                    table.Append(row);
                }
                yield return(new Paragraph(new Run(new Text("")))
                {
                    ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                        Val = "TableLineBefore"
                    })
                });

                yield return(table);

                yield return(new Paragraph(new Run(new Text("")))
                {
                    ParagraphProperties = new ParagraphProperties(new ParagraphStyleId {
                        Val = "TableLineAfter"
                    })
                });
            }
            else
            {
                yield return(new Paragraph(new Run(new Text($"[{md.GetType().Name}]"))));
            }
        }