Пример #1
0
        private static FrozenFragment CreateTextFragment(FrozenFragment parent, ref string c, IList <ManifestItem> data)
        {
            // if no text just proceed
            if (c.Length == 0)
            {
                return(parent);
            }
            // close open tags or open closed tags
            HtmlDocument nodeCheck = new HtmlDocument();

            nodeCheck.OptionAutoCloseOnEnd = true;
            nodeCheck.OptionCheckSyntax    = true;
            nodeCheck.OptionFixNestedTags  = true;
            nodeCheck.LoadHtml(c);
            if (nodeCheck.ParseErrors.Count() > 0)
            {
                // handle parser errors
            }
            var f = new FrozenFragment {
                Name           = "Paragraph",
                TypeOfFragment = FragmentType.Html,
                Parent         = parent
            };
            var body = nodeCheck.DocumentNode.SelectSingleNode("//body");

            CreateEmbeddedImages(f, body, data);
            f.Content = UTF8Encoding.UTF8.GetBytes(body.InnerHtml);
            parent.Children.Add(f);
            c = String.Empty;
            return(f);
        }
Пример #2
0
        /// <summary>
        /// Create the final HTML from a frozen fragment. There is no scaling or file handling as the frozen fragments are ready to go.
        /// </summary>
        /// <param name="fragment"></param>
        /// <param name="withNumbers"></param>
        /// <returns></returns>
        public string CreateFragmentHtml(FrozenFragment fragment, CreateImageHandler createImage, ScaleImageHandler scaleImage, bool withNumbers = true)
        {
            var flatFragments = fragment.Children.FlattenHierarchy()
                                .Where(f => f.TypeOfFragment == FragmentType.Html)
                                .ToList();
            var sb = new StringBuilder();

            sb.AppendLine(Encoding.UTF8.GetString(fragment.Content));
            flatFragments.Select(f => sb.AppendLine(Encoding.UTF8.GetString(f.Content)));
            var fragmentContent = sb.ToString();

            // assume children provide resources
            if (fragment.HasChildren())
            {
                foreach (var resources in fragment.Children)
                {
                    var imgRegex = new Regex(String.Format(@"src=""{0}""", resources.ItemHref));
                    if (!imgRegex.Match(fragmentContent).Success)
                    {
                        continue;
                    }
                    var newPath = createImage(this, new CreateImageArguments {
                        FileName = resources.ItemHref
                    });
                    fragmentContent = imgRegex.Replace(fragmentContent, String.Format(@"src=""{0}""", newPath));
                }
            }
            return(fragmentContent);
        }
Пример #3
0
        public void Convert(EpubBook book, Published p, PortalContext context)
        {
            Published = p;
            Context   = context;
            // 1. The spine is used to create one single document as a source
            var spineIds = book.PackageData.Spine.ItemRefs.Select(i => i.IdRef).ToList();
            // all elements
            var data = book.PackageData.Manifest.Items;
            // 2. Get the content elements only
            var content = data.Where(i => spineIds.Any(sid => sid == i.Identifier)).Select(i => i).ToList();
            // fragments form a hierarchy, beginning with <h1> on the first level
            FrozenFragment rootFragment = new FrozenFragment {
                Name           = book.PackageData.MetaData.Title.Text,
                ItemHref       = "Opus (Import)",
                Published      = p,
                TypeOfFragment = FragmentType.Meta,
                Children       = new List <FrozenFragment>()
            };

            switch (_method)
            {
            case Method.NcxToc:
            case Method.Html:
                // 3. Create source
                var complete = new StringBuilder();
                complete.AppendLine("<body>");
                foreach (var html in content)
                {
                    complete.AppendFormat(@"<a name=""{0}"" ></a>", html.Identifier);
                    complete.Append(GetBodyFromManifest(html.Data));
                }
                complete.AppendLine("</body>");
                // 5.
                HtmlDocument allHtml = new HtmlDocument();
                allHtml.OptionAutoCloseOnEnd = true;
                allHtml.OptionFixNestedTags  = true;
                allHtml.OptionOutputAsXml    = true;
                allHtml.LoadHtml(complete.ToString());
                var body = allHtml.DocumentNode.SelectSingleNode("//body");
                switch (_method)
                {
                case Method.NcxToc:
                    NcxParser(book, body, rootFragment);
                    break;

                case Method.Html:
                    var htmlConverter = new HtmlToFrozenFragments();
                    htmlConverter.Convert(body.InnerHtml, data);
                    break;
                }
                break;

            case Method.Spine:
                SpineParser(content, rootFragment, data);
                break;
            }
            //Context.SaveChanges();
        }
Пример #4
0
        private string CreateDataFragment(FrozenFragment fragment)
        {
            // identify fragment
            // get attribute
            string content;

            switch (fragment.TypeOfFragment)
            {
            case FragmentType.Html:
                content = System.Text.Encoding.UTF8.GetString(fragment.Content);
                break;

            default:
                // TODO: Implement this
                throw new NotImplementedException();
            }
            return(content);
        }
Пример #5
0
        public FrozenFragment Convert(string html, IList <ManifestItem> resources)
        {
            var allHtml = new HtmlDocument {
                OptionAutoCloseOnEnd = true, OptionFixNestedTags = true, OptionOutputAsXml = true
            };

            allHtml.LoadHtml(html);

            // fragments form a hierarchy, beginning with <h1> on the first level
            var rootFragment = new FrozenFragment {
                Name           = "Root",
                ItemHref       = "root",
                TypeOfFragment = FragmentType.Meta,
                Children       = new List <FrozenFragment>(),
                Published      = null
            };
            var c    = String.Empty; // current content for text snippet
            var body = allHtml.DocumentNode.SelectSingleNode("//body");

            ElementParser(body.ChildNodes, rootFragment, resources);
            return(rootFragment);
        }
Пример #6
0
        private static void SpineParser(EpubBook book, Published p)
        {
            var spineIds = book.PackageData.Spine.ItemRefs.Select(i => i.IdRef).ToList();
            var data     = book.PackageData.Manifest.Items;
            // 2. Get the content elements
            var content = data.Where(i => spineIds.Any(sid => sid == i.Identifier)).Select(i => new {
                Data       = i.Data,
                Identifier = i.Href,
                Name       = i.Identifier
            });
            FrozenFragment rootFragment = new FrozenFragment {
                Name           = "Root",
                TypeOfFragment = FragmentType.Meta,
                Children       = new List <FrozenFragment>()
            };
            int orderNr = 1;

            foreach (var file in content)
            {
                var c = UTF8Encoding.UTF8.GetString(file.Data);
                CreateTextFragment(rootFragment, ref c, data);
            }
            p.FrozenFragments = rootFragment.Children;
        }
Пример #7
0
 private static void CreateEmbeddedImages(FrozenFragment parent, HtmlNode element, IList <ManifestItem> data)
 {
     if (element.SelectNodes(".//img") == null)
     {
         return;
     }
     foreach (var img in element.SelectNodes(".//img"))
     {
         var alt = img.Attributes["alt"] != null ? img.Attributes["alt"].Value : "Generic Image";
         var cnt = data.FirstOrDefault(d => img.Attributes["src"].Value.EndsWith(d.Href));
         var r   = new FrozenFragment {
             Name           = alt,
             Content        = cnt.Data,
             TypeOfFragment = FragmentType.Image,
             ItemHref       = Guid.NewGuid().ToString()
         };
         if (parent.Children == null)
         {
             parent.Children = new List <FrozenFragment>();
         }
         parent.Children.Add(r);
         img.Attributes["src"].Value = r.ItemHref;
     }
 }
Пример #8
0
        private void ElementParser(IEnumerable <HtmlNode> elements, FrozenFragment rootFragment, IList <ManifestItem> data)
        {
            // loop through all first level children
            FrozenFragment activeFragment = rootFragment;
            string         c = "";

            foreach (var element in elements)
            {
                string e = element.Name.ToLower();
                // Text elements are kept in a single fragment if they contain more than exactly one container
                if (textElements.Contains(e))
                {
                    if (element.HasChildNodes)
                    {
                        // if the only element is a container, keep the container and throw the element away
                        if (element.ChildNodes.Count() == 1)
                        {
                            var subel   = element.ChildNodes.Single();
                            var subname = element.ChildNodes.Single().Name.ToLower();
                            if (contElements.Contains(subname))
                            {
                                CreateTextFragment(activeFragment, ref c, data);
                                switch (subname)
                                {
                                case "table":
                                    Debug.WriteLine("inner table " + element.OuterHtml);
                                    CreateTableFragment(activeFragment, subel, data);
                                    break;

                                case "img":
                                    Debug.WriteLine("inner image " + element.OuterHtml);
                                    CreateImageFragment(activeFragment, subel, data);
                                    break;
                                }
                                continue;
                            }
                        }
                    }
                    // collect element until we reach another container or header
                    c += element.OuterHtml;
                }
                //
                if (headElements.Contains(e))
                {
                    // detect current header element
                    int l = 0;
                    // detect level where we already are
                    int h = activeFragment.Level;
                    // get where we need to be
# pragma warning disable CS0462
                    if (e.StartsWith("h") && e.Length == 2 && Int32.TryParse(e.Substring(1), out l))
                    {
                        ;
                    }
# pragma warning restore CS0462
                    l++; // zero based
                    Debug.WriteLine("hx h:{0} l:{1}", h, l);
                    // each section writes the current text
                    CreateTextFragment(activeFragment, ref c, data);
                    if (l == 1)
                    {
                        // first level
                        activeFragment = CreateSectionFragment(activeFragment, element);
                        h = 0;
                    }
                    else
                    {
                        if (l == h)
                        {
                            // same level = add to current parent
                            activeFragment = CreateSectionFragment(activeFragment.Parent, element);
                        }
                        if (l > h)
                        {
                            // one level deeper = add to last current
                            activeFragment = CreateSectionFragment(activeFragment, element);
                        }
                        if (l < h)
                        {
                            // one level higher = add again to former parent
                            while (activeFragment.Parent != null && activeFragment.Level >= l)
                            {
                                activeFragment = activeFragment.Parent;
                            }
                            activeFragment = CreateSectionFragment(activeFragment, element);
                        }
                    }
                    continue;
                }
        /// <summary>
        /// The builder itself, creates the HTML from property data using reflection.
        /// </summary>
        /// <param name="snippet">The source snippet</param>
        /// <param name="numbering"> </param>
        /// <param name="targetFragment"></param>
        /// <returns>The final HTML string</returns>
        public string BuildHtml(Element snippet, IDictionary <string, NumberingSchema> numbering, FrozenFragment targetFragment)
        {
            if (String.IsNullOrEmpty(HtmlPattern))
            {
                return(snippet.RawContent);
            }
            var t = snippet.WidgetName;

            if (numbering != null)
            {
                if (numbering.ContainsKey(t) && snippet is NumberedSnippet)
                {
                    // set regular snippets
                    ((NumberedSnippet)snippet).Divider   = numbering[t].Divider;
                    ((NumberedSnippet)snippet).Minor     = numbering[t].Minor;
                    ((NumberedSnippet)snippet).Label     = numbering[t].Label;
                    ((NumberedSnippet)snippet).Separator = numbering[t].Separator;
                    ((NumberedSnippet)snippet).Major     = numbering[t].Major;
                    numbering[t].Minor = numbering[t].Minor + 1;
                }
                else
                {
                    // special treatment for sections
                    if (snippet is Section)
                    {
                        var d = snippet.Level - 1;
                        var s = t + d;
                        ((Section)snippet).SetCounterString(numbering[s].Separator);
                    }
                }
            }
            // assign properties to the builder string
            var type     = snippet.GetType();
            var propVals = new object[Properties.Length];

            for (var i = 0; i < propVals.Length; i++)
            {
                PropertyInfo prop = null;
                try {
                    prop = type.GetProperty(Properties[i]);
                    if (prop == null)
                    {
                        throw new ArgumentOutOfRangeException("Builder Attribute provided wrong properties for object of type " + type);
                    }
                    if (prop.GetIndexParameters().Length > 0)
                    {
                        propVals[i] = prop.GetValue(snippet, new object[] { Target, targetFragment });
                    }
                    else
                    {
                        propVals[i] = prop.GetValue(snippet);
                    }
                } catch (Exception ex) {
                    Debug.WriteLine(ex.Message, prop == null ? propVals[i] : prop.Name);
                }
            }
            return(String.Format(HtmlPattern, propVals));
        }
Пример #10
0
        /// <summary>
        /// Create this Element as HTML and process down with all children.
        /// </summary>
        /// <param name="snippets">Create HTML for these snippets in distinct order, section resolve their children independently.</param>
        /// <param name="target">The current production target the builder is working for.</param>
        /// <param name="targetFragment"></param>
        /// <returns></returns>
        protected string CreateChildren(IEnumerable <Snippet> snippets, GroupKind target, FrozenFragment targetFragment)
        {
            Element opus = this;

            do
            {
                opus = opus.Parent;
            } while (!(opus is Opus));
            var numbering            = ((Opus)opus).Numbering;
            var flatContent          = new StringBuilder();
            Action <Snippet> convert = null;

            convert = e => {
                var builder = e.GetType().GetCustomAttributes(typeof(SnippetBuilderAttribute), true).OfType <SnippetBuilderAttribute>().First(sb => sb.Target == target);
                flatContent.Append(builder.BuildHtml(e, numbering, targetFragment));
            };
            snippets.OrderBy(s => s.OrderNr).ToList().ForEach(c => convert(c));
            return(flatContent.ToString());
        }
Пример #11
0
 public abstract string this[GroupKind target, FrozenFragment targetFragment] {
     get;
 }