Beispiel #1
0
        private static void ProcessBullets(Md2MlEngine engine, string markdown)
        {
            // Split the text block into a list of items
            var lines = Regex.Split(markdown, "\r\n|\r|\n").ToArray();

            engine.MarkdownList(engine, lines);
        }
Beispiel #2
0
        /// <summary>
        /// TODO : Problem to fix, all lists are represented as Numbered...
        /// Process an array of markdown items of a list (with spaces to define the item level)
        /// The pattern can be detected as a CodeBlock pattern, so fix it with the try catch.
        /// I should probably not let defining a CodeBlock with spaces and tabulations,
        /// but only with tabulations... (WIP)
        /// </summary>
        /// <param name="core"></param>
        /// <param name="bulletedItems">Items of a list, split in an array by break lines</param>
        /// <param name="paragraphStyle"></param>
        public void MarkdownList(Md2MlEngine core, string[] bulletedItems, string paragraphStyle = "ParagraphList")
        {
            foreach (var item in bulletedItems)
            {
                // Detect if item is ordered or not
                var matchedPattern = PatternMatcher.GetMarkdownMatch(item);
                if (matchedPattern.Key != ParaPattern.OrderedList && matchedPattern.Key != ParaPattern.UnorderedList)
                {
                    try
                    {
                        matchedPattern = PatternMatcher.GetMatchFromPattern(item, ParaPattern.OrderedList);
                    }
                    catch (Exception e)
                    {
                        matchedPattern = PatternMatcher.GetMatchFromPattern(item, ParaPattern.UnorderedList);
                    }
                }
                // Then count spaces 3 by 3 to define the level of the item
                var nbSpaces = matchedPattern.Value.Groups[0].Value.TakeWhile(Char.IsWhiteSpace).Count();;
                var itemLvl  = nbSpaces / 3;
                // Then Create paragraph, properties and format the text
                Paragraph               paragraph1               = CreateParagraph(paragraphStyle);
                NumberingProperties     numberingProperties1     = new NumberingProperties();
                NumberingLevelReference numberingLevelReference1 = new NumberingLevelReference()
                {
                    Val = itemLvl
                };
                NumberingId numberingId1 = GetListType(matchedPattern.Key);

                numberingProperties1.Append(numberingLevelReference1);
                numberingProperties1.Append(numberingId1);
                paragraph1.ParagraphProperties.Append(numberingProperties1);
                MarkdownStringParser.FormatText(core, paragraph1, matchedPattern.Value.Groups[2].Value, new StyleProperties());
            }
        }
        public static void FormatText(Md2MlEngine core, Paragraph paragraph, string markdown, FontProperties fontProperties)
        {
            var hasPattern = PatternMatcher.HasPatterns(markdown);

            while (hasPattern)
            {
                var s                 = PatternMatcher.GetPatternsAndNonPatternText(markdown);
                var count             = s.Value.Count();
                var NewFontProperties = new FontProperties();
                switch (s.Key)
                {
                case RunPattern.BoldAndItalic:
                    NewFontProperties.Bold   = true;
                    NewFontProperties.Italic = true;
                    FormatText(core, paragraph, s.Value[0], new FontProperties());
                    FormatText(core, paragraph, s.Value[1], NewFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "***"), new FontProperties());
                    break;

                case RunPattern.Bold:
                    NewFontProperties.Bold = true;
                    FormatText(core, paragraph, s.Value[0], new FontProperties());
                    FormatText(core, paragraph, s.Value[1], NewFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "**"), new FontProperties());
                    break;

                case RunPattern.Italic:
                    NewFontProperties.Italic = true;
                    FormatText(core, paragraph, s.Value[0], new FontProperties());
                    FormatText(core, paragraph, s.Value[1], NewFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "*"), new FontProperties());
                    break;

                case RunPattern.MonospaceOrCode:
                    NewFontProperties.StyleName = "InlineCodeChar";
                    FormatText(core, paragraph, s.Value[0], new FontProperties());
                    FormatText(core, paragraph, s.Value[1], NewFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "`"), new FontProperties());
                    break;

                case RunPattern.Strikethrough:
                    NewFontProperties.Strikeout = true;
                    FormatText(core, paragraph, s.Value[0], new FontProperties());
                    FormatText(core, paragraph, s.Value[1], NewFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "~~"), new FontProperties());
                    break;

                case RunPattern.Underline:
                    NewFontProperties.Underline = UnderlineValues.Single;
                    FormatText(core, paragraph, s.Value[0], new FontProperties());
                    FormatText(core, paragraph, s.Value[1], NewFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "__"), new FontProperties());
                    break;
                }
                return;
            }
            core.WriteText(paragraph, markdown, fontProperties);
        }
        private static void ProcessTable(Md2MlEngine core, List <string> markdown)
        {
            var table = core.CreateTable(markdown.First().Trim('|').Split('|').Count());

            core.AddTableRow(table, markdown.First().Trim(new char[] { '|' }).Split('|').ToList());
            foreach (var data in markdown.Skip(2))
            {
                core.AddTableRow(table, data.Trim(new char[] { '|' }).Split('|').ToList());
            }
        }
 public static void ProcessBullets(Md2MlEngine core, List <string> bullets, bool ordered = false)
 {
     if (bullets.Count != 0)
     {
         if (ordered)
         {
             core.MarkdownNumberedList(core, bullets);
         }
         else
         {
             core.MarkdownBulletedList(core, bullets);
         }
         bullets.Clear();
     }
 }
Beispiel #6
0
        /// <summary>
        /// Process a full string block of a markdown table.
        /// Split it by rows
        /// Create the Table with correct number of columns
        /// Fill the openXML table
        /// </summary>
        /// <param name="engine"></param>
        /// <param name="markdown">The complete markdown table, must be correctly formatted</param>
        private static void ProcessTable(Md2MlEngine engine, string markdown)
        {
            var rows       = Regex.Split(markdown, "\r\n|\r|\n");
            var firstLine  = rows.First();
            var secondLine = rows.Length >= 2 ? rows.Skip(1).First() : null;
            var table      = engine.CreateTable(firstLine.Trim('|').Split('|').Count());

            engine.AddTableRow(table, firstLine.Trim('|').Split('|').ToList());
            var patternSecondLine = PatternMatcher.GetMarkdownMatch(secondLine).Key;

            if (string.IsNullOrEmpty(secondLine) ||
                (patternSecondLine != ParaPattern.TableHeaderSeparation && patternSecondLine != ParaPattern.TableHeaderSeparation)) // TODO : Throw error : Table not well formatted
            {
                return;
            }

            // Define the table alignment properties
            List <JustificationValues> cellJustification = new List <JustificationValues>();
            var nbCols          = secondLine.Trim('|').Split('|').Count();
            var secondLineCells = secondLine.Trim('|').Split('|').ToList();

            for (int i = 0; i < nbCols; i++)
            {
                var justification = JustificationValues.Left;
                if (secondLineCells[i].StartsWith(":") && secondLineCells[i].EndsWith(":"))
                {
                    justification = JustificationValues.Center;
                }
                else if (!secondLineCells[i].StartsWith(":") && secondLineCells[i].EndsWith(":"))
                {
                    justification = JustificationValues.Right;
                }

                cellJustification.Add(justification);
            }

            // Process the rest of the table
            foreach (var row in rows.Skip(2).ToList())
            {
                engine.AddTableRow(table, row.Trim('|').Split('|').ToList(), cellJustification);
            }
        }
Beispiel #7
0
 public void MarkdownBulletedList(Md2MlEngine core, List <string> bulletedItems, string paragraphStyle)
 {
     foreach (var item in bulletedItems)
     {
         Paragraph               paragraph1               = CreateParagraph(paragraphStyle);
         NumberingProperties     numberingProperties1     = new NumberingProperties();
         NumberingLevelReference numberingLevelReference1 = new NumberingLevelReference()
         {
             Val = 0
         };
         NumberingId numberingId1 = new NumberingId()
         {
             Val = 1
         };
         numberingProperties1.Append(numberingLevelReference1);
         numberingProperties1.Append(numberingId1);
         paragraph1.ParagraphProperties.Append(numberingProperties1);
         MarkdownStringParser.FormatText(core, paragraph1, item, new FontProperties());
     }
 }
        public static void Parse(Md2MlEngine engine, string mdText)
        {
            var lineAndPattern = new List <KeyValuePair <ParaPattern, string[]> >();
            var lines          = mdText.Split('\n');

            foreach (var line in lines)
            {
                lineAndPattern.Add(PatternMatcher.GetParagraphType(line));
            }
            bool          OrderedList   = false;
            bool          UnorderedList = false;
            bool          Table         = false;
            List <string> BulletItems   = new List <string>();
            List <string> NumberItems   = new List <string>();
            List <string> TableData     = new List <string>();

            foreach (var line in lineAndPattern)
            {
                Paragraph para;
                switch (line.Key)
                {
                case ParaPattern.OrderedList:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (UnorderedList)
                    {
                        ProcessBullets(engine, BulletItems, false); UnorderedList = false;
                    }
                    OrderedList = true;
                    NumberItems.Add(line.Value[1]);
                    break;

                case ParaPattern.UnorderedList:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList)
                    {
                        ProcessBullets(engine, NumberItems, true); OrderedList = false;
                    }
                    UnorderedList = true;
                    BulletItems.Add(line.Value[1]);
                    break;

                case ParaPattern.Image:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph();
                    if (line.Value[2].StartsWith("http://") || line.Value[2].StartsWith("https://"))
                    {
                        engine.AddImage(new System.Net.WebClient().OpenRead(line.Value[2]));
                    }
                    else
                    {
                        engine.AddImage(System.IO.File.OpenRead(line.Value[2]));
                    }
                    break;

                case ParaPattern.Table:
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    Table = true;
                    TableData.Add(line.Value[1]);
                    break;

                case ParaPattern.CodeBlock:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = "CodeBlock"
                    });
                    engine.WriteText(para, line.Value[1]);
                    break;

                case ParaPattern.Heading1:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = "Heading1"
                    });
                    engine.WriteText(para, line.Value[1]);
                    break;

                case ParaPattern.Heading2:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = "Heading2"
                    });
                    engine.WriteText(para, line.Value[1]);
                    break;

                case ParaPattern.Heading3:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = "Heading3"
                    });
                    engine.WriteText(para, line.Value[1]);
                    break;

                case ParaPattern.Quote:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = "Quote"
                    });
                    engine.WriteText(para, line.Value[1]);
                    break;

                case ParaPattern.CommanBlock:
                default:
                    if (Table)
                    {
                        ProcessTable(engine, TableData); Table = false;
                    }
                    if (OrderedList || UnorderedList)
                    {
                        ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
                    }
                    para = engine.CreateParagraph();
                    FormatText(engine, para, line.Value[1], new FontProperties());
                    //core.WriteText(para, line.Value[1]);
                    break;
                }
            }
            if (Table)
            {
                ProcessTable(engine, TableData); Table = false;
            }
            if (OrderedList || UnorderedList)
            {
                ProcessBullets(engine, OrderedList ? NumberItems : BulletItems, OrderedList); OrderedList = false; UnorderedList = false;
            }
        }
Beispiel #9
0
        /// <summary>
        /// Parse the content, and detect all real lines breaks.
        /// In fact, within markdown it is possible to write a unique paragraph, with line breaks.
        /// If there is not a double space before the line break, it's the same paragraph, and the line break is not interpreted as is.
        ///
        /// So in this parsing method, cut the content by "block" with same nature.
        ///		1| Detect the paragraph type by the start of the line
        ///		2| Process the content by its type
        ///		3| Then remove the processed content, and continue to parse the next content
        ///
        /// A block is detected by a <see cref="ParaPattern"/> which have an associated regex.
        ///
        /// </summary>
        /// <param name="engine">Describe an openXML object by code</param>
        /// <param name="mdText">The markdown text to parse</param>
        internal static void Parse(Md2MlEngine engine, string mdText)
        {
            while (!string.IsNullOrEmpty(mdText))
            {
                var       firstLine      = GetFirstLine(mdText);
                var       matchedPattern = PatternMatcher.GetMarkdownMatch(firstLine);
                Paragraph para;
                (int counter, string textBlock)rebuildText = default;
                switch (matchedPattern.Key)
                {
                case ParaPattern.InfiniteHeading:
                    string titleChars = matchedPattern.Value.Groups[1].Value;
                    int    titleLvl   = titleChars.Count(c => c == '#');
                    titleLvl = titleLvl <= 9 ? titleLvl : 9;
                    para     = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = string.Concat("Heading", titleLvl.ToString())
                    });
                    engine.WriteText(para, matchedPattern.Value.Groups[2].Value);
                    mdText = DeleteLines(mdText);
                    continue;

                case ParaPattern.Image:
                    var link = matchedPattern.Value.Groups[2].Value;
                    if (link.StartsWith("http://") || link.StartsWith("https://"))
                    {
                        engine.AddImage(new System.Net.WebClient().OpenRead(link));
                    }
                    else
                    {
                        engine.AddImage(ConvertRelativeToAbsolutePath(link, engine.GetFileDirectory()));
                    }
                    mdText = DeleteLines(mdText);
                    continue;

                case ParaPattern.Table:
                    //case ParaPattern.TableHeaderSeparation:
                    rebuildText = BuildWithoutBreakingLines(mdText, ParaPattern.Table);
                    ProcessTable(engine, rebuildText.textBlock);
                    mdText = DeleteLines(mdText, rebuildText.counter);
                    continue;

                case ParaPattern.OrderedList:
                case ParaPattern.UnorderedList:
                    // TODO : Ordered list can contain unordered items inside and vice versa
                    rebuildText = BuildWithoutBreakingLines(mdText, ParaPattern.OrderedList);
                    ProcessBullets(engine, rebuildText.textBlock);
                    mdText = DeleteLines(mdText, rebuildText.counter);
                    continue;

                case ParaPattern.CodeBlock:
                    // TODO : Improve the rendering - not a priority for my needs
                    rebuildText = BuildWithoutBreakingLines(mdText, ParaPattern.CodeBlock);
                    para        = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = DocStyles.CodeBlock.ToDescriptionString()
                    });
                    FormatText(engine, para, rebuildText.textBlock, new StyleProperties());
                    mdText = DeleteLines(mdText, rebuildText.counter);
                    continue;

                case ParaPattern.Quote:
                    // Markdown supports nested quotes, but word does not
                    // So whatever, put the "nested" paragraph in the same quote
                    rebuildText = BuildWithoutBreakingLines(mdText, ParaPattern.Quote);
                    para        = engine.CreateParagraph(new ParaProperties()
                    {
                        StyleName = DocStyles.Quote.ToDescriptionString()
                    });
                    foreach (var text in Regex.Split(rebuildText.textBlock, "\r\n|\r|\n"))
                    {
                        para.AppendChild(new Break());
                        FormatText(engine, para, text, new StyleProperties());
                    }
                    mdText = DeleteLines(mdText, rebuildText.counter);
                    continue;

                case ParaPattern.AnyChar:
                default:
                    rebuildText = BuildWithoutBreakingLines(mdText, matchedPattern.Key);
                    para        = engine.CreateParagraph();
                    FormatText(engine, para, rebuildText.textBlock, new StyleProperties());
                    // engine.WriteText(para, text.textBlock);
                    mdText = DeleteLines(mdText, rebuildText.counter);
                    continue;
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Format a paragraph which could contains some text styles, Bold, Italics, Images and so on...
        /// Split the markdown for each pattern found. Then append correctly that text or image into the same paragraph.
        /// </summary>
        /// <param name="core">The openXML object with a document, a body and a paragraph</param>
        /// <param name="paragraph">The Paragraph object previously created</param>
        /// <param name="markdown">The string to be processed</param>
        /// <param name="fontProperties">Style properties to apply to the text</param>
        internal static void FormatText(Md2MlEngine core, Paragraph paragraph, string markdown,
                                        StyleProperties fontProperties)
        {
            var hasPattern = PatternMatcher.HasPatterns(markdown);

            while (hasPattern)
            {
                var s = PatternMatcher.GetPatternsAndNonPatternText(markdown);
                var newFontProperties = new StyleProperties();

                switch (s.Key)
                {
                case StylePattern.BoldAndItalic:
                    newFontProperties.Bold   = true;
                    newFontProperties.Italic = true;
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    FormatText(core, paragraph, s.Value[1], newFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "***"), new StyleProperties());
                    break;

                case StylePattern.Bold:
                    newFontProperties.Bold = true;
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    FormatText(core, paragraph, s.Value[1], newFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "**"), new StyleProperties());
                    break;

                case StylePattern.Italic:
                    newFontProperties.Italic = true;
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    FormatText(core, paragraph, s.Value[1], newFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "*"), new StyleProperties());
                    break;

                case StylePattern.MonospaceOrCode:
                    newFontProperties.StyleName = DocStyles.CodeReference.ToDescriptionString();
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    FormatText(core, paragraph, s.Value[1], newFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "`"), new StyleProperties());
                    break;

                case StylePattern.Strikethrough:
                    newFontProperties.Strikeout = true;
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    FormatText(core, paragraph, s.Value[1], newFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "~~"), new StyleProperties());
                    break;

                case StylePattern.Image:
                    var regex = PatternMatcher.GetStyleMatch(s.Value[1]);
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    core.AddImage(ConvertRelativeToAbsolutePath(regex.Value.Groups[2].Value, core.GetFileDirectory()), paragraph);
                    FormatText(core, paragraph, FramePendingString(s.Value, ""), new StyleProperties());
                    break;

                case StylePattern.Underline:
                    newFontProperties.Underline = UnderlineValues.Single;
                    FormatText(core, paragraph, s.Value[0], new StyleProperties());
                    FormatText(core, paragraph, s.Value[1], newFontProperties);
                    FormatText(core, paragraph, FramePendingString(s.Value, "__"), new StyleProperties());
                    break;
                }
                return;
            }
            core.WriteText(paragraph, markdown, fontProperties);
        }
Beispiel #11
0
 public void MarkdownBulletedList(Md2MlEngine core, List <string> bulletedItems) => MarkdownBulletedList(core, bulletedItems, "ListParagraph");