Пример #1
0
 public void AddItem(ParagraphLineItem item)
 {
     _items.Add(item);
 }
        IEnumerable <ParagraphLine> readLines()
        {
            // We're processing "blocks" out of the lexer. Blocks are either:
            // - xml tags - these will always come in as a single block
            // - slabs of text - these will come one per line (but they may have a tag breaking up two slabs on the one line).
            //
            // We need to break them into what we think the lines should be.

            // Start reading blocks from the lexer
            ParagraphLine paragraphLine = new ParagraphLine();

            foreach (string block in _xmlBlockLexer)
            {
                // Create a new item to put this block into.
                ParagraphLineItem item = new ParagraphLineItem();

                // If the block is a code or "c" block then we treat the block as a single, non-reflowable chunk.
                if (block.StartsWith("<code") || block.StartsWith("<c") || block.StartsWith("<see") || block.StartsWith("<paramref") || block.StartsWith("<typeparamref"))
                {
                    item.Text     = block;
                    item.ItemType = ItemType.NonReflowableBlock;
                    paragraphLine.AddItem(item);
                }
                // If the block is some other xml tag then treat it as a line (we may compress these again later).
                else if (block.StartsWith("<"))
                {
                    /*
                     * // Yield the previous line
                     * yield return paragraphLine;
                     *
                     * // Create a new line
                     * paragraphLine = new ParagraphLine();
                     */
                    // And add the new tag into it
                    item.Text     = block;
                    item.ItemType = ItemType.XmlElement;
                    paragraphLine.AddItem(item);

                    /*
                     * // Yield that
                     * yield return paragraphLine;
                     *
                     * // Create a new line
                     * paragraphLine = new ParagraphLine();
                     */
                }
                // Otherwise it must be a text block so deal with that.
                else
                {
                    // Split the text block into lines
                    string[] lines = block.Replace("\r", "").Split('\n');

                    // Process each line
                    for (int i = 0; i < lines.Length; i++)
                    {
                        // Create an item for this line
                        string line = lines[i];
                        item.Text     = line;
                        item.ItemType = line.Trim().Length == 0 ? ItemType.XmlSpace : ItemType.Text;
                        paragraphLine.AddItem(item);

                        // If we're not the last line then yield this line (last line may contain other sections).
                        if (i != lines.Length - 1)
                        {
                            yield return(paragraphLine);

                            item          = new ParagraphLineItem();
                            paragraphLine = new ParagraphLine();
                        }
                    }
                }
            }

            if (paragraphLine.Items.Count > 0)
            {
                yield return(paragraphLine);
            }
        }
        public string ReflowToLineLength(IEnumerable <Paragraph> paragraphs, int maxLineLength)
        {
            LineBuilder lb = new LineBuilder();

            bool firstParagraph = true;

            foreach (Paragraph paragraph in paragraphs)
            {
                if (!firstParagraph)
                {
                    lb.Append("\r\n");
                }

                ParagraphLineItem previousItem = null;
                foreach (ParagraphLine paragraphLine in paragraph.Lines)
                {
                    foreach (ParagraphLineItem lineItem in paragraphLine.Items)
                    {
                        if (lineItem.ItemType == ItemType.XmlElement ||
                            lineItem.ItemType == ItemType.NonReflowableBlock)
                        {
                            if ( //if current line is empty, no matter how big text is, just append it (to
                                // not create extra lines.
                                lb.CurrentLine.Trim().Length > 0 &&
                                //Append new line otherwise
                                lb.CurrentLine.Length + lineItem.FirstLine.Length > maxLineLength)
                            {
                                lb.AppendMultilineBlock("\r\n" + paragraph.Offset);
                            }
                            lb.AppendMultilineBlock(lineItem.Text);
                        }

                        //Space between XML elements is not reflown.
                        else if (lineItem.ItemType == ItemType.XmlSpace)
                        {
                            if (previousItem != null && previousItem.IsForcingNewLine)
                            {
                                // do not create new line if it is the last item
                                // in the paragraph
                                if ((lineItem != paragraphLine.Items[paragraphLine.Items.Count - 1]) ||
                                    (paragraphLine != paragraph.Lines[paragraph.Lines.Count - 1]))
                                {
                                    lb.AppendMultilineBlock(
                                        "\r\n" + paragraph.Offset);
                                }
                            }
                            else
                            {
                                lb.AppendMultilineBlock(lineItem.Text);
                            }
                        }

                        else if (lineItem.ItemType == ItemType.Text)
                        {
                            string text = lineItem.Text;
                            if (lineItem == paragraphLine.Items[0])
                            {
                                text = text.TrimStart();
                            }

                            if (previousItem != null && previousItem.IsForcingNewLine)
                            {
                                lb.AppendMultilineBlock("\r\n" + paragraph.Offset);
                                text = text.TrimStart();
                            }

                            string[] words = text.Split(' ');

                            for (int i = 0; i < words.Length; i++)
                            {
                                // append the space at the start of the line
                                if (lb.CurrentLine.Length == 0)
                                {
                                    lb.AppendMultilineBlock(paragraph.Offset);
                                }

                                string word = words[i];

                                if (lb.CurrentLine.Length == paragraph.Offset.Length && word.Trim().Length == 0)
                                {
                                    continue;
                                }

                                //prepend space if this is not first word in block and not first word on paragraph line
                                //or this is first word in block and block is appended to previous line.
                                bool   previousBlockIsText = previousItem != null && previousItem.ItemType == ItemType.Text;
                                string toAppend            = (lb.CurrentLine.Length > paragraph.Offset.Length && (i > 0 || previousBlockIsText) ? " " : "") + word;
                                if (lb.CurrentLine.Length + toAppend.Length > maxLineLength)
                                {
                                    lb.AppendMultilineBlock("\r\n" + paragraph.Offset);
                                    toAppend = word;
                                }

                                lb.AppendMultilineBlock(toAppend);
                            }
                        }
                        previousItem = lineItem;
                    }
                }
                firstParagraph = false;
            }

            return(lb.ToString());
        }