Auto Create Hierarchical Bookmarks

EVO HTML to PDF Converter can be configured to automatically create a hierarchy of bookmarks in PDF document based on H1 to H6 head tags found in HTML document by simply turning on the PdfDocumentOptionsGenerateDocumentOutline option. An object of PdfDocumentOptions type is exposed by the HtmlToPdfConverterPdfDocumentOptions property.

If the bookmarks auto-creation is enabled, you can further choose a custom algorithm to generate the bookmarks or use the internal capabilities of the browser using the PdfDocumentOptionsUseBrowserOutlineMode property. By default, a custom algorithm is used.

In the custom mode, you can also mark arbitrary HTML elements as bookmarks using the data-heading attribute, as described in the section below.

Custom Bookmarks Using the data-heading Attribute

Besides the standard H1 to H6 heading tags, any HTML element can be turned into a bookmark by setting the data-heading attribute to a level from 1 to 6, for example data-heading="2". The bookmark title is taken from the data-heading-text attribute when present, otherwise from the element text. A real heading can be excluded from the bookmarks by setting data-heading="false". The custom data-heading attribute is honored only when the custom bookmark mode is used, that is when PdfDocumentOptionsUseBrowserOutlineMode is false.

The HTML below shows how to mark ordinary elements as bookmarks together with the standard heading tags.

XML
<!DOCTYPE html>
<html>
<head>
    <title>Auto Create Bookmarks</title>
    <link href="styles/webfonts.css" type="text/css" rel="stylesheet">
    <style>
        body {
            font-family: Verdana, sans-serif;
            font-size: 16px;
        }
    </style>
</head>
<body>
    <br />
    <br />
    <h1>Contents</h1>
    <a href="#Chapter1">Go To Chapter 1</a>
    <br />
    <a href="#Chapter2">Go To Chapter 2</a>
    <br />
    <a href="#Chapter3">Go To Chapter 3</a>
    <br />
    <a href="#CustomBookmarks">Go To Custom Bookmarks</a>
    <br />
    <h2 style="page-break-before: always" id="Chapter1">Chapter 1</h2>
    This is the chapter 1 content.
    <h2 style="page-break-before: always" id="Chapter2">Chapter 2</h2>
    This is the chapter 2 content.
    <h2 style="page-break-before: always" id="Chapter3">Chapter 3</h2>
    This is the chapter 3 content.

    <!-- Custom bookmarks created with the data-heading attribute.
     Any element (not only H1-H6) becomes a bookmark when it has a data-heading
     attribute with a valid level (1 to 6). -->
    <h2 style="page-break-before: always" id="CustomBookmarks">Custom Bookmarks Example</h2>
    These bookmarks are created from ordinary elements using the data-heading attribute.
    <div data-heading="3">Custom Bookmark - Level 3</div>
    This section was bookmarked using a custom &lt;div&gt; element with data-heading="3".
    <div data-heading="3" data-heading-text="Custom Bookmark With Explicit Title">This visible text is ignored for the bookmark</div>
    This section uses data-heading-text to set the bookmark title independently of the element text.
    <h3 data-heading="false">Excluded Heading (data-heading="false")</h3>
    This is a real H3 heading, but it is excluded from the bookmarks because of data-heading="false".

    <p><i>Note: The custom data-heading attribute is enabled only when the custom bookmark mode is used.</i></p>
</body>
</html>

Code Sample - Auto Create Hierarchical Bookmarks

C#
using System;
using System.IO;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using EvoPdf_Next_AspNetDemo.Models;
using EvoPdf_Next_AspNetDemo.Models.HTML_to_PDF;

// Use EVO PDF Namespace
using EvoPdf.Next;

namespace EvoPdf_Next_AspNetDemo.Controllers.HTML_to_PDF
{
    public class Auto_Create_BookmarksController : Controller
    {
        private readonly IWebHostEnvironment m_hostingEnvironment;
        public Auto_Create_BookmarksController(IWebHostEnvironment hostingEnvironment)
        {
            m_hostingEnvironment = hostingEnvironment;
        }

        public ActionResult Index()
        {
            var model = SetViewModel();

            return View(model);
        }

        [HttpPost]
        public ActionResult ConvertHtmlToPdf(Auto_Create_Bookmarks_ViewModel model)
        {
            if (!ModelState.IsValid)
            {
                var errorMessage = ModelStateHelper.GetModelErrors(ModelState);
                throw new ValidationException(errorMessage);
            }

            // Set license key received after purchase to use the converter in licensed mode
            // Leave it not set to use the library in demo mode
            Licensing.LicenseKey = "3FJDU0ZDU0NTQkddQ1NAQl1CQV1KSkpKU0M=";

            // Create a HTML to PDF converter object with default settings
            HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();

            // Auto Create a hierarchy of bookmarks from H1 to H6 tags found in HTML
            if (model.GenerateDocumentOutline)
            {
                // Enable the creation of a hierarchy of bookmarks from H1 to H6 tags
                htmlToPdfConverter.PdfDocumentOptions.GenerateDocumentOutline = model.GenerateDocumentOutline;

                htmlToPdfConverter.ConversionDelay = 2;

                // Optionally, enable the outline mode to utilize browser capabilities. By default, a custom algorithm is used
                htmlToPdfConverter.PdfDocumentOptions.UseBrowserOutlineMode = model.UseBrowserOutlineMode;

                // Display the bookmarks panel in PDF viewer when the generated PDF is opened
                htmlToPdfConverter.PdfViewerPreferences.PageMode = ViewerPageMode.UseOutlines;
            }

            // The buffer to receive the generated PDF document
            byte[] outPdfBuffer = null;

            if (model.HtmlPageSource == "Url")
            {
                string url = model.Url;

                // Convert the HTML page given by an URL to a PDF document in a memory buffer
                outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);
            }
            else
            {
                string htmlString = model.HtmlStringTextBox;
                string baseUrl = model.BaseUrlTextBox;

                // Convert a HTML string with a base URL to a PDF document in a memory buffer
                outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlString, baseUrl);
            }

            // Send the PDF file to browser
            FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
            fileResult.FileDownloadName = "Auto_Create_Hierarchical_Bookmarks.pdf";

            return fileResult;
        }

        private Auto_Create_Bookmarks_ViewModel SetViewModel()
        {
            var model = new Auto_Create_Bookmarks_ViewModel();

            var contentRootPath = Path.Combine(m_hostingEnvironment.ContentRootPath, "wwwroot");

            HttpRequest request = ControllerContext.HttpContext.Request;
            UriBuilder uriBuilder = new UriBuilder();
            uriBuilder.Scheme = request.Scheme;
            uriBuilder.Host = request.Host.Host;
            if (request.Host.Port != null)
                uriBuilder.Port = (int)request.Host.Port;
            uriBuilder.Path = request.PathBase.ToString() + request.Path.ToString();
            uriBuilder.Query = request.QueryString.ToString();

            string currentPageUrl = uriBuilder.Uri.AbsoluteUri;
            string rootUrl = currentPageUrl.Substring(0, currentPageUrl.Length - "Auto_Create_Bookmarks".Length);

            model.HtmlStringTextBox = System.IO.File.ReadAllText(Path.Combine(contentRootPath, "DemoAppFiles/Input/HTML_Files/Auto_Bookmarks.html"));
            model.BaseUrlTextBox = rootUrl + "DemoAppFiles/Input/HTML_Files/";

            return model;
        }
    }
}

See Also