Example #1
0
        protected XElement GetListStyleElement(List <Paragraph> listItems)
        {
            string listType;

            if (listItems[0].Range.ListFormat.ListType == WdListType.wdListBullet)
            {
                listType = "ul";
            }
            else
            {
                listType = "ol";
            }
            var currentListElement = new XElement(listType);

            currentListElement.SetAttributeValue("class", "carrot-list");
            XElement        rootListElement = currentListElement;
            WordStyleStruct wstyle;
            Style           style = listItems[0].get_Style();

            if (style != null && ParagraphStyles.TryGetValue(style.NameLocal, out wstyle))
            {
                rootListElement.SetAttributeValue("class", wstyle.CssClass);
            }
            int previousIndentLevel = listItems[0].Range.ListFormat.ListLevelNumber;

            foreach (Paragraph item in listItems)
            {
                var liElement = new XElement("li");
                liElement = CharacterStyleTransformer.GetCharacterStyledElement(liElement, item,
                                                                                CharacterStyleFactory.GetCharacterStyles(), false);
                int currentIndentLevel = item.Range.ListFormat.ListLevelNumber;
                if (currentIndentLevel > previousIndentLevel)
                {
                    var sublist = new XElement(listType);
                    var li      = liElement;
                    sublist.Add(li);
                    if (currentListElement != null)
                    {
                        currentListElement.Add(sublist);
                    }
                    currentListElement = sublist;
                }
                else
                {
                    int delta = previousIndentLevel - currentIndentLevel;
                    for (int i = 0; i < delta; i++)
                    {
                        if (currentListElement != null)
                        {
                            currentListElement = currentListElement.Parent;
                        }
                    }
                    if (currentListElement != null)
                    {
                        XElement li = liElement;
                        currentListElement.Add(li);
                    }
                }
                previousIndentLevel = currentIndentLevel;
            }

            return(rootListElement);
        }
Example #2
0
        /// <summary>
        /// Takes the list of paragraphs and returns the XML representation of these elements.
        /// </summary>
        /// <param name="paragraphs">The list of paragraphs to parse.</param>
        /// <param name="tableBuilder"></param>
        /// <param name="builder"></param>
        /// <returns>An XElement representation of the document.</returns>
        public XElement ParagraphsToXml(List <Paragraph> paragraphs, TableBuilder tableBuilder, Object builder = null)
        {
            SidebarArticleParser = new SidebarArticleParser();
            WdListType previouslistType = paragraphs[0].Range.ListFormat.ListType;
            bool       previousWasList  = false;

            string previousIFrameStyle = string.Empty;

            bool          previousWasIFrame           = false;
            bool          desktopCodeFound            = false;
            bool          currentIframeIsInsecure     = false;
            bool          currentContainsInvalidNodes = false;
            List <string> insecureIFrames             = new List <string>();
            bool          containsInvalidNodes        = false;

            string   iframeGroupId      = String.Empty;
            XElement iframeGroupElement = new XElement("div");

            iframeGroupElement.SetAttributeValue("class", "iframe-component");

            bool          previousWasBlockquote        = false;
            var           contiguousListElements       = new List <Paragraph>();
            var           contiguousBlockquoteElements = new List <Paragraph>();
            List <string> StylesToIgnore = ArticleDocumentMetadataParser.GetInstance().MetadataStyles;
            Paragraph     lastParagraph  = null;
            //var xData = new XElement("root");
            var xData = new XElement("div");

            xData.SetAttributeValue("class", "root");
            Errors = new List <string>();
            int      imageTagCount = 0;
            XElement divElement    = null;

            for (int i = 0; i < paragraphs.Count; i++)
            {
                Paragraph paragraph = paragraphs[i];
                int       tIndex    = tableBuilder == null ? -1 : tableBuilder.GetTableIndexFor(paragraph.Range);

                Style style = (Style)paragraph.get_Style();


                if (tableBuilder != null && tIndex != -1 && tableBuilder.HasRetrieved(tIndex))
                {
                    continue;
                }

                var currentStyle = (Style)paragraph.get_Style();
                if (StylesToIgnore.Contains(currentStyle.NameLocal))
                {
                    continue;
                }

                XElement   xElement        = null;
                bool       isList          = paragraph.Range.ListParagraphs.Count > 0;
                bool       isBlockquote    = currentStyle.NameLocal == BlockquoteName;
                WdListType currentListType = paragraph.Range.ListFormat.ListType;

                if (tableBuilder != null && tIndex != -1 && !tableBuilder.HasRetrieved(tIndex))
                {
                    xData.Add(tableBuilder.ParseTable(tIndex));
                    continue;
                }


                if (builder != _quickFactsSideboxParser && _quickFactsSideboxParser != null &&
                    _quickFactsSideboxParser.Match(currentStyle.NameLocal))
                {
                    _quickFactsSideboxParser.Add(paragraph);
                    continue;
                }
                if (_quickFactsSideboxParser != null && !_quickFactsSideboxParser.Match(currentStyle.NameLocal) &&
                    !_quickFactsSideboxParser.IsEmpty())
                {
                    xData.Add(_quickFactsSideboxParser.GetSidebox(this));
                    _quickFactsSideboxParser.Clear();
                }

                lastParagraph = paragraph;
                if (currentStyle.NameLocal == SidebarArticleParser.SidebarStyle)
                {
                    try
                    {
                        xData.Add(paragraph.Range.Text);
                        SidebarArticleParser.RetrieveSidebarToken(paragraph);
                    }
                    catch (ArgumentException e)
                    {
                        Errors.Add(e.Message);
                    }
                    continue;
                }
                if (!isList && previousWasList)
                {
                    xData.Add(GetListStyleElement(contiguousListElements));
                    contiguousListElements = new List <Paragraph>();
                    previousWasList        = false;
                }
                if (!isBlockquote && previousWasBlockquote)
                {
                    xData.Add(BlockquoteTransformer.Generate(contiguousBlockquoteElements, CharacterStyleTransformer));
                    contiguousBlockquoteElements = new List <Paragraph>();
                    previousWasBlockquote        = false;
                }

                if (isBlockquote)
                {
                    contiguousBlockquoteElements.Add(paragraph);
                    previousWasBlockquote = true;
                    //just forming contiguous blocks, no further processing
                    continue;
                }
                if (isList)
                {
                    if (previouslistType != currentListType && contiguousListElements.Count > 0)
                    {
                        xElement = GetListStyleElement(contiguousListElements);

                        xData.Add(xElement);
                        contiguousListElements = new List <Paragraph>();
                    }
                    //add paragraph to bloc,
                    //even if new list has been started, we are adding it now
                    contiguousListElements.Add(paragraph);
                    previousWasList  = true;
                    previouslistType = paragraph.Range.ListFormat.ListType;
                    //just forming contiguous blocks, no further processing
                    continue;
                }


                if (style.NameLocal == DocumentAndParagraphStyles.IFrameCodeStyle ||
                    style.NameLocal == DocumentAndParagraphStyles.IFrameMobileCodeStyle)
                {
                    var iframeElement = new XElement("div");

                    if (!previousWasIFrame)
                    {
                        iframeGroupId = Guid.NewGuid().ToString("N");

                        previousWasIFrame = true;
                        iframeGroupElement.SetAttributeValue("class", "iframe-component");
                    }
                    string cssStyle = string.Empty;

                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameCodeStyle)
                    {
                        desktopCodeFound = true;
                        cssStyle         = String.Format("ewf-desktop-iframe_{0}", iframeGroupId);
                        iframeElement.SetAttributeValue("class", $"iframe-component__desktop {cssStyle}");
                        iframeElement.SetAttributeValue("data-mediaid", iframeGroupId);
                    }

                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameMobileCodeStyle)
                    {
                        cssStyle = String.Format("ewf-mobile-iframe_{0}", iframeGroupId);
                        iframeElement.SetAttributeValue("class", $"iframe-component__mobile {cssStyle}");
                    }

                    var insecureIFramesInParagraph = HTMLTools.CheckForInsecureIFrames(paragraph.Range.Text);
                    currentIframeIsInsecure = insecureIFramesInParagraph.Any() || currentIframeIsInsecure;
                    insecureIFrames.AddRange(insecureIFramesInParagraph);

                    currentContainsInvalidNodes = HTMLTools.ContainsForExternalNodes(paragraph.Range.Text);
                    containsInvalidNodes        = containsInvalidNodes || currentContainsInvalidNodes;
                    XElement embedElement = IFrameEmbedBuilder.Parse(paragraph, cssStyle, true);
                    if (embedElement != null)
                    {
                        iframeElement.SetAttributeValue("data-embed-link", "enabled");
                        iframeElement.Add(embedElement);
                        iframeGroupElement.Add(iframeElement);
                    }
                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameMobileCodeStyle)
                    {
                        xData.Add(iframeGroupElement);
                        iframeGroupElement = new XElement("div");
                        iframeGroupElement.SetAttributeValue("class", "iframe-component");
                    }

                    previousIFrameStyle = style.NameLocal;
                    continue;
                }

                if (IFrameEmbedBuilder.IFrameStyles.Contains(style.NameLocal))
                {
                    WordStyleStruct w = new WordStyleStruct();
                    //base styles are used becuase the parent level styles only exist in the plugin
                    var baseStyle = (Style)style.get_BaseStyle();
                    if (baseStyle != null)
                    {
                        ParagraphStyles.TryGetValue(baseStyle.NameLocal, out w);
                    }

                    XElement curElement   = new XElement("p");
                    string   stylesection = String.Empty;
                    bool     isNewIframe  = false;
                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameHeaderStyle)
                    {
                        stylesection = "header";
                        isNewIframe  = true;
                    }
                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameTitleStyle)
                    {
                        stylesection = "title";
                        isNewIframe  = previousIFrameStyle != DocumentAndParagraphStyles.IFrameHeaderStyle;
                    }
                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameCaptionStyle)
                    {
                        stylesection = "caption";
                        isNewIframe  = previousIFrameStyle != DocumentAndParagraphStyles.IFrameMobileCodeStyle;
                    }

                    if (style.NameLocal == DocumentAndParagraphStyles.IFrameSourceStyle)
                    {
                        stylesection = "source";
                        isNewIframe  = previousIFrameStyle != DocumentAndParagraphStyles.IFrameCaptionStyle &&
                                       previousIFrameStyle != DocumentAndParagraphStyles.IFrameMobileCodeStyle;
                    }


                    if (!previousWasIFrame && isNewIframe)
                    {
                        iframeGroupId     = Guid.NewGuid().ToString("N");
                        previousWasIFrame = true;
                    }

                    string cssClass      = w == null ? string.Empty : w.CssClass;
                    string iframeIdClass = String.Format("{0}-{1}_{2}", IFrameEmbedBuilder.IFrameClassName, stylesection,
                                                         iframeGroupId);

                    curElement.SetAttributeValue("class",
                                                 String.Format("{0} {1}",
                                                               cssClass,
                                                               iframeIdClass));

                    curElement = CharacterStyleTransformer.GetCharacterStyledElement(curElement, paragraph,
                                                                                     CharacterStyleFactory.GetCharacterStyles(), false);
                    xData.Add(curElement);

                    previousIFrameStyle = style.NameLocal;
                    continue;
                }
                else //redundant else but adds code clarity
                {
                    if (currentIframeIsInsecure || currentContainsInvalidNodes ||
                        (!desktopCodeFound && previousWasIFrame))
                    {
                        xData.Elements()
                        .Where(x => x.Attribute("class") != null &&
                               x.Attribute("class").Value.Contains(iframeGroupId))
                        .Remove();
                    }
                    previousIFrameStyle         = String.Empty;
                    previousWasIFrame           = false;
                    currentIframeIsInsecure     = false;
                    currentContainsInvalidNodes = false;
                    desktopCodeFound            = false;
                }

                if (ImageReferenceBuilder.Parse(paragraph) != null)
                {
                    if (imageTagCount == 0)
                    {
                        divElement = new XElement("section");
                        divElement.SetAttributeValue("class", "article-exhibit");
                        xData.Add(divElement);
                    }

                    //Get the float Value from the image hyperlink (if it is an image) and set it to the article-image element
                    var hyprlnk = paragraph.Range.Hyperlinks.Cast <Hyperlink>().FirstOrDefault();
                    if (hyprlnk != null && string.IsNullOrEmpty(hyprlnk.ScreenTip) == false)
                    {
                        string classValue;
                        classValue = imageFloatDictionary.TryGetValue(hyprlnk.ScreenTip.ToLower(), out classValue) ? classValue : string.Empty;
                        divElement.SetAttributeValue("class", classValue);
                    }

                    var imageTag = ImageReferenceBuilder.Parse(paragraph);
                    divElement.Add(imageTag);
                    imageTagCount++;
                    continue;
                }

                imageTagCount = 0;

                WordStyleStruct styleStruct;
                if (ParagraphStyles.TryGetValue(currentStyle.NameLocal, out styleStruct))
                {
                    //if there is a special configuration for the paragraph style, have it configured properly
                    string element = styleStruct.CssElement;
                    if (element.IsNullOrEmpty())
                    {
                        element = null;
                    }
                    string clas = styleStruct.CssClass;
                    if (clas.IsNullOrEmpty())
                    {
                        clas = null;
                    }
                    XElement curElement = element != null ? new XElement(element) : new XElement("p");
                    if (!string.IsNullOrWhiteSpace(clas))
                    {
                        curElement.SetAttributeValue("class", clas);
                    }

                    xElement = CharacterStyleTransformer.GetCharacterStyledElement(curElement, paragraph,
                                                                                   CharacterStyleFactory.GetCharacterStyles(), false);

                    //The next section is group multiple paragraphs belonging to the same answer under the same Answer element to prevent multiple answer styling on front-end for a single answer
                    if (clas == "article-interview__answer")
                    {
                        while (paragraphs.Count > i + 1)//If there are still more element to inspect
                        {
                            //Get the styling of the next element
                            var             tempAnswerStyle = (Style)paragraphs[i + 1].get_Style();
                            WordStyleStruct tempAnswerStyleStruct;
                            //Get the cssClass of the next element
                            ParagraphStyles.TryGetValue(tempAnswerStyle.NameLocal, out tempAnswerStyleStruct);
                            //if it is also an answer paragraph
                            if (tempAnswerStyleStruct.CssClass == clas)
                            {
                                //add the the next paragraph content into the current answer body
                                xElement.Add(CharacterStyleTransformer.GetCharacterStyledElement(new XElement("p"), paragraphs[i + 1], CharacterStyleFactory.GetCharacterStyles(), false));
                                i++;
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    xElement = new XElement("p");
                    xElement = CharacterStyleTransformer.GetCharacterStyledElement(xElement, paragraph,
                                                                                   CharacterStyleFactory.GetCharacterStyles(), false);
                }
                xData.Add(xElement);
                previouslistType = paragraph.Range.ListFormat.ListType;
            }
            if (insecureIFrames.Any())
            {
                var confirmSave =
                    MessageBox.Show("You have inserted multimedia items using non-secure links. " +
                                    "Click 'OK' to continue saving the article without this content or 'Cancel'" +
                                    " to go back into the article and edit your multimedia items.",
                                    "Continue with save?",
                                    MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                if (confirmSave != DialogResult.OK)
                {
                    throw new InsecureIFrameException(insecureIFrames);
                }
            }
            if (containsInvalidNodes)
            {
                var confirmSave =
                    MessageBox.Show("You have inserted multimedia items with invalid or non-permitted HTML code. " +
                                    "Click 'OK' to continue saving the article without this content or 'Cancel' to " +
                                    "go back into the article and edit your multimedia items.", "Continue with save?",
                                    MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                if (confirmSave != DialogResult.OK)
                {
                    throw new InvalidHtmlException();
                }
            }
            if (lastParagraph != null && lastParagraph.Range.ListParagraphs.Count > 0)
            {
                xData.Add(GetListStyleElement(contiguousListElements));
            }
            if (lastParagraph != null && ((Style)lastParagraph.get_Style()).NameLocal == BlockquoteName)
            {
                xData.Add(BlockquoteTransformer.Generate(contiguousBlockquoteElements, CharacterStyleTransformer));
            }
            if (_quickFactsSideboxParser != null && builder != _quickFactsSideboxParser &&
                !_quickFactsSideboxParser.IsEmpty())
            {
                xData.Add(_quickFactsSideboxParser.GetSidebox(this));
                _quickFactsSideboxParser.Clear();
            }
            return(xData);
        }