Пример #1
0
 private IEnumerable <Inline> ConvertInlines(HTML.Element e, Context ctx, bool collapseSpace, ParagraphSizeTracker pst)
 {
     return(from i in
            (from n in e.Contents select ConvertInline(n, ctx, collapseSpace, pst))
            where i != null
            select i);
 }
Пример #2
0
 private Span RenderHyperlink(HTML.Element e)
 {
     if (e.Attributes.ContainsKey("href"))
     {
         Hyperlink h = new Hyperlink();
         Uri       TargetURI;
         if (Uri.TryCreate(e.Attributes["href"], UriKind.RelativeOrAbsolute, out TargetURI))
         {
             if (!TargetURI.IsAbsoluteUri)
             {
                 TargetURI = BaseUri != null ? new Uri(BaseUri, TargetURI) : null;
             }
         }
         if (TargetURI != null)
         {
             h.NavigateUri      = TargetURI;
             h.RequestNavigate += RequestedNavigate;
             h.ToolTip          = TargetURI;
         }
         else
         {
             // tooltip contains URI even if it's bad
             h.ToolTip = e.Attributes["href"];
         }
         return(h);
     }
     else
     {
         return(new Span());
     }
 }
Пример #3
0
        private InlineUIContainer RenderImage(HTML.Element e, ParagraphSizeTracker pst)
        {
            Uri ImageURI;

            if (e.Attributes.ContainsKey("src") &&
                Uri.TryCreate(e.Attributes["src"], UriKind.RelativeOrAbsolute, out ImageURI))
            {
                Image image = new Image()
                {
                    Stretch = Stretch.Fill
                };
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.UriSource = ImageURI;
                bitmapImage.EndInit();
                image.Source = bitmapImage;
                if (ImageSizeCache.ContainsKey(ImageURI))
                {
                    Tuple <int, int> size = ImageSizeCache[ImageURI];
                    image.Width  = size.Item1;
                    image.Height = size.Item2;
                }
                // This hack forces image size to match pixel size,
                // which undermines WPF's preference for honoring the
                // embedded DPI value which leads to upscaled and
                // mildly blurry images where that doesn't match
                // the local display.  Very high resolution displays
                // might need another approach.
                bitmapImage.DownloadCompleted += (s, ee) =>
                {
                    ImageSizeCache[ImageURI] = new Tuple <int, int>(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
                    image.Width  = bitmapImage.PixelWidth;
                    image.Height = bitmapImage.PixelHeight;
                };
                // Communicate image size info back up to the container
                if (pst != null)
                {
                    pst.Add(image);
                }
                if (e.Attributes.ContainsKey("title"))
                {
                    image.ToolTip = e.Attributes["title"];
                }
                else if (e.Attributes.ContainsKey("alt"))
                {
                    image.ToolTip = e.Attributes["alt"];
                }
                // TODO arrange to display alt value if image can't be loaded
                // (or before it has loaded)
                return(new InlineUIContainer()
                {
                    Child = image
                });
            }
            else
            {
                return(null);
            }
        }
Пример #4
0
 public void TestHTMLSimpleNoOpen()
 {
     HTML.Document d = HTML.Document.Parse("wibble");
     HTML.Element  p = d.HTML.Follow("body.p");
     Assert.AreEqual(1, p.Contents.Count);
     HTML.Cdata cdata = p.Contents[0] as HTML.Cdata;
     Assert.AreEqual("wibble", cdata.Content);
 }
Пример #5
0
        private IEnumerable <Block> ConvertFlowsOrBlocks(HTML.Element root, Context ctx)
        {
            List <Block> blocks = new List <Block>();

            foreach (HTML.Node n in root.Contents)
            {
                blocks.AddRange(ConvertFlowOrBlock(n as HTML.Element, ctx));
            }
            return(blocks);
        }
Пример #6
0
 public void TestHTMLEmpty()
 {
     HTML.Document d = HTML.Document.Parse("");
     Assert.AreEqual("html", d.HTML.Name);
     Assert.AreEqual(2, d.HTML.Contents.Count);
     HTML.Element body = d.HTML.Contents[1] as HTML.Element;
     Assert.IsNotNull(body);
     Assert.AreEqual("body", body.Name);
     Assert.AreEqual(0, body.Contents.Count);
 }
Пример #7
0
 public void TestHTMLExtraSlash()
 {
     HTML.Document d   = HTML.Document.Parse("<img src=\"http://imgs.xkcd.com/comics/voyager_1.png\" title=\"what'ever'\" />");
     HTML.Element  img = d.HTML.Follow("body.p.img");
     Assert.AreEqual(2, img.Attributes.Count);
     Assert.IsTrue(img.Attributes.ContainsKey("src"));
     Assert.AreEqual("http://imgs.xkcd.com/comics/voyager_1.png", img.Attributes["src"]);
     Assert.IsTrue(img.Attributes.ContainsKey("title"));
     Assert.AreEqual("what'ever'", img.Attributes["title"]);
     Assert.AreEqual("<html><head></head><body><p><img src=\"http://imgs.xkcd.com/comics/voyager_1.png\" title=\"what'ever'\"></p></body></html>", d.ToString());
 }
Пример #8
0
        private Paragraph ConvertParagraph(HTML.Element e, Context ctx, bool collapseSpace)
        {
            LastCharacter = ' ';
            Paragraph p = new Paragraph();

            p.Inlines.AddRange(ConvertInlines(e, ctx, collapseSpace,
                                              new ParagraphSizeTracker()
            {
                ParentScrollViewer = ParentScrollViewer
            }));
            return(p.Inlines.Count > 0 ? p : null);
        }
Пример #9
0
        private List ConvertList(HTML.Element e, Context ctx)
        {
            List l = new List();

            foreach (HTML.Element ee in e.Contents)
            {
                ListItem li = new ListItem();
                li.Blocks.AddRange(ConvertFlowOrBlock(ee, ctx));
                l.ListItems.Add(li);
            }
            return(l);
        }
Пример #10
0
 public void TestHTMLTwoPara()
 {
     HTML.Document d = HTML.Document.Parse("<p>first</p> <p>second</p>");
     Assert.AreEqual(2, d.HTML.Follow("body").Contents.Count);
     HTML.Element p1 = d.HTML.Follow("body.p");
     Assert.AreEqual(1, p1.Contents.Count);
     HTML.Cdata cdata1 = p1.Contents[0] as HTML.Cdata;
     Assert.AreEqual("first", cdata1.Content);
     HTML.Element p2     = (HTML.Element)d.HTML.Follow("body").Contents[1];
     HTML.Cdata   cdata2 = p2.Contents[0] as HTML.Cdata;
     Assert.AreEqual("second", cdata2.Content);
 }
Пример #11
0
 public void TestHTMLInline()
 {
     HTML.Document d = HTML.Document.Parse("<p>one <i>two</i> three</p>");
     HTML.Element  p = d.HTML.Follow("body.p");
     Assert.AreEqual(3, p.Contents.Count);
     HTML.Cdata cdata1 = p.Contents[0] as HTML.Cdata;
     Assert.AreEqual("one ", cdata1.Content);
     HTML.Element italic = p.Contents[1] as HTML.Element;
     Assert.AreEqual("i", italic.Name);
     Assert.AreEqual(1, italic.Contents.Count);
     HTML.Cdata cdata2 = italic.Contents[0] as HTML.Cdata;
     Assert.AreEqual("two", cdata2.Content);
     HTML.Cdata cdata3 = p.Contents[2] as HTML.Cdata;
     Assert.AreEqual(" three", cdata3.Content);
 }
Пример #12
0
 public void TestHTMLSimple()
 {
     HTML.Document d = HTML.Document.Parse("<p>wibble</p>");
     Assert.AreEqual("html", d.HTML.Name);
     Assert.AreEqual(2, d.HTML.Contents.Count);
     HTML.Element body = d.HTML.Contents[1] as HTML.Element;
     Assert.IsNotNull(body);
     Assert.AreEqual("body", body.Name);
     Assert.AreEqual(1, body.Contents.Count);
     HTML.Element p = body.Contents[0] as HTML.Element;
     Assert.AreEqual("p", p.Name);
     Assert.AreEqual(1, p.Contents.Count);
     HTML.Cdata cdata = p.Contents[0] as HTML.Cdata;
     Assert.AreEqual("wibble", cdata.Content);
 }
Пример #13
0
        private IEnumerable <Block> ConvertDefinitionList(HTML.Element e, Context ctx)
        {
            List <Block> blocks = new List <Block>();

            foreach (HTML.Element d in e.Contents)
            {
                IEnumerable <Block> dblocks = ConvertFlowOrBlock(d, ctx);
                if (d.Name == "dd")
                {
                    foreach (Block b in dblocks)
                    {
                        Indent(b, 12, 0);
                    }
                }
                blocks.AddRange(dblocks);
            }
            return(blocks);
        }
Пример #14
0
        static private int GetSpan(HTML.Element e, string attribute)
        {
            string attributeValue;

            if (e.Attributes.TryGetValue(attribute, out attributeValue))
            {
                int value;
                if (int.TryParse(attributeValue, out value))
                {
                    if (value < 1)
                    {
                        value = 1;
                    }
                    return(value);
                }
            }
            return(1);
        }
Пример #15
0
        public void TestHTMLAttributes()
        {
            HTML.Document d = HTML.Document.Parse("<p><a href=\"http://www.example.com/\">target</a></p>");
            HTML.Element  a = d.HTML.Follow("body.p.a");
            Assert.AreEqual(1, a.Attributes.Count);
            Assert.IsTrue(a.Attributes.ContainsKey("href"));
            Assert.AreEqual("http://www.example.com/", a.Attributes["href"]);

            d = HTML.Document.Parse("<p><a href='http://www.example.com/&amp;' >target</a></p>");
            a = d.HTML.Follow("body.p.a");
            Assert.AreEqual(1, a.Attributes.Count);
            Assert.IsTrue(a.Attributes.ContainsKey("href"));
            Assert.AreEqual("http://www.example.com/&", a.Attributes["href"]);

            d = HTML.Document.Parse("<p><a href=\"http://www.example.com/\" Target=_blank>target</a></p>");
            a = d.HTML.Follow("body.p.a");
            Assert.AreEqual(2, a.Attributes.Count);
            Assert.IsTrue(a.Attributes.ContainsKey("href"));
            Assert.AreEqual("http://www.example.com/", a.Attributes["href"]);
            Assert.IsTrue(a.Attributes.ContainsKey("target"));
            Assert.AreEqual("_blank", a.Attributes["target"]);
        }
Пример #16
0
        public void TestHTMLLists()
        {
            HTML.Document d  = HTML.Document.Parse("<ul><li>one</li><li>two</li></ul>");
            HTML.Element  ul = d.HTML.Follow("body.ul");
            Assert.AreEqual(2, ul.Contents.Count);
            HTML.Element li1 = ul.Contents[0] as HTML.Element;
            Assert.AreEqual("li", li1.Name);
            Assert.AreEqual(1, li1.Contents.Count);
            Assert.AreEqual("one", (li1.Contents[0] as HTML.Cdata).Content);
            HTML.Element li2 = ul.Contents[1] as HTML.Element;
            Assert.AreEqual("li", li2.Name);
            Assert.AreEqual(1, li2.Contents.Count);
            Assert.AreEqual("two", (li2.Contents[0] as HTML.Cdata).Content);

            d  = HTML.Document.Parse("<ul><li><p>one<p>two</ul>");
            ul = d.HTML.Follow("body.ul");
            Assert.AreEqual(1, ul.Contents.Count);
            li1 = ul.Contents[0] as HTML.Element;
            Assert.AreEqual("li", li1.Name);
            Assert.AreEqual(2, li1.Contents.Count);
            Assert.AreEqual("one", ((li1.Contents[0] as HTML.Element).Contents[0] as HTML.Cdata).Content);
            Assert.AreEqual("two", ((li1.Contents[1] as HTML.Element).Contents[0] as HTML.Cdata).Content);
        }
Пример #17
0
        private Table ConvertTable(HTML.Element e, Context ctx)
        {
            Table t = new Table()
            {
                CellSpacing = 0,
            };
            TableRowGroup trg = new TableRowGroup();

            t.RowGroups.Add(trg);
            int columns = 0;

            HTML.Element caption = null;
            foreach (HTML.Element r in e.Contents)
            {
                switch (r.Name)
                {
                case "tr":
                    TableRow tr = new TableRow();
                    trg.Rows.Add(tr);
                    int columnNumber = 0;
                    foreach (HTML.Element c in r.Contents)
                    {
                        TableCell tc = new TableCell()
                        {
                            ColumnSpan      = GetSpan(c, "colspan"),
                            RowSpan         = GetSpan(c, "rowspan"),
                            BorderBrush     = Brushes.Black,
                            BorderThickness = new Thickness(0.5, 0.5, 0.5, 0.5),
                            Padding         = new Thickness(1),
                        };
                        if (c.Name == "th")
                        {
                            tc.Blocks.AddRange(ConvertFlowOrBlock(c, new Context(ctx)
                            {
                                fontWeight = FontWeights.Bold
                            }));
                        }
                        else
                        {
                            tc.Blocks.AddRange(ConvertFlowOrBlock(c, ctx));
                        }
                        tr.Cells.Add(tc);
                        columnNumber += tc.ColumnSpan;
                    }
                    if (columnNumber > columns)
                    {
                        columns = columnNumber;
                    }
                    break;

                case "caption":
                    caption = r;
                    break;
                }
            }
            if (caption != null && columns == 0)
            {
                columns = 1;
            }
            for (int i = 0; i < columns; ++i)
            {
                t.Columns.Add(new TableColumn());
            }
            if (caption != null)
            {
                TableRow  tr = new TableRow();
                TableCell tc = new TableCell()
                {
                    ColumnSpan    = columns,
                    TextAlignment = TextAlignment.Center,
                };
                Paragraph p = ConvertParagraph(caption,
                                               new Context(ctx)
                {
                    fontStyle = FontStyles.Italic
                },
                                               true);
                tc.Blocks.Add(p);
                tr.Cells.Add(tc);
                trg.Rows.Add(tr);
            }
            return(t);
        }
Пример #18
0
        private IEnumerable <Block> ConvertFlowOrBlock(HTML.Element e, Context ctx)
        {
            if (e.IsBlockElement() ||
                e.IsListElement() ||
                e.IsTableElement())
            {
                Block block = null;
                switch (e.Name)
                {
                case "ul":
                    block = ConvertList(e, ctx);
                    break;

                case "ol":
                    List l = ConvertList(e, ctx);
                    l.StartIndex = 1;
                    block        = l;
                    break;

                case "dl":
                    return(ConvertDefinitionList(e, ctx));

                case "h1":
                case "h2":
                case "h3":
                case "h4":
                case "h5":
                case "h6":
                    block = ConvertParagraph(e,
                                             new Context(ctx)
                    {
                        fontFamily = HeadingFont, fontWeight = FontWeights.Bold, fontSize = TextSize * Math.Pow(1.125, '7' - e.Name[1])
                    },
                                             true);
                    break;

                case "pre":
                    block = ConvertParagraph(e,
                                             new Context(ctx)
                    {
                        fontFamily = MonospaceFont
                    },
                                             false);
                    break;

                case "table":
                    block = ConvertTable(e, ctx);
                    break;

                case "hr":
                    block = HorizontalRule();
                    break;

                default:
                    block = ConvertParagraph(e, ctx, true);
                    break;
                }
                if (block != null)
                {
                    return(new List <Block>()
                    {
                        block
                    });
                }
                else
                {
                    return(new List <Block>());
                }
            }
            else
            {
                IEnumerable <Block> content;
                if (e.Contents.Count > 0 &&
                    (e.Contents[0] is HTML.Cdata ||
                     (e.Contents[0] as HTML.Element).IsInlineElement()))
                {
                    content = new List <Block>()
                    {
                        ConvertParagraph(e, ctx, true)
                    };
                }
                else
                {
                    content = ConvertFlowsOrBlocks(e, ctx);
                }
                switch (e.Name)
                {
                case "blockquote":
                    foreach (Block b in content)
                    {
                        Indent(b, 12, 12);
                        break;
                    }
                    break;
                    // TODO other kinds of flow container
                }
                return(content);
            }
        }
Пример #19
0
        private Inline ConvertInlineElement(HTML.Element e, Context ctx, bool collapseSpace, ParagraphSizeTracker pst)
        {
            Span s;

            switch (e.Name)
            {
            case "b":
            case "strong":
                s   = new Span();
                ctx = new Context(ctx)
                {
                    fontWeight = FontWeights.Bold
                };
                break;

            case "i":
            case "em":
                s   = new Span();
                ctx = new Context(ctx)
                {
                    fontStyle = FontStyles.Italic
                };
                break;

            case "u":
                s = new Underline();
                break;

            case "big": {
                s = new Span();
                double newSize = ctx.fontSize * 1.25;
                ctx = new Context(ctx)
                {
                    fontSize = newSize
                };
                break;
            }

            case "small": {
                s = new Span();
                double newSize = ctx.fontSize / 1.25;
                ctx = new Context(ctx)
                {
                    fontSize = newSize
                };
                break;
            }

            case "code":
            case "tt":
                s   = new Span();
                ctx = new Context(ctx)
                {
                    fontFamily = MonospaceFont
                };
                break;

            case "sub":
                s = new Span();
                s.Typography.Variants = FontVariants.Subscript;
                break;

            case "sup":
                s = new Span();
                s.Typography.Variants = FontVariants.Superscript;
                break;

            case "a":
                s = RenderHyperlink(e);
                break;

            case "img":
                return(RenderImage(e, pst));

            case "br":
                return(new LineBreak());

            // TODO map, anything else?
            default: s = new Span(); break;
            }
            s.Inlines.AddRange(ConvertInlines(e, ctx, collapseSpace, pst));
            return(s);
        }