Create Outlines, Internal Links and Table of Contents in PDF

If your HTML is structured using the heading tags H1 to H6, you can use the PdfDocumentControlGenerateDocumentOutline option to automatically create a hierarchy of outlines based on the document structure.

If bookmark auto-creation is enabled, you can either use a custom algorithm to generate bookmarks or use the browser capabilities by setting the PdfDocumentControlUseBrowserOutlineMode property. By default, a custom algorithm is used.

The HTML document below contains both internal and HTTP links, and the HTML to PDF converter is configured to automatically generate a table of contents with outlines for chapters.

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 PdfDocumentControlUseBrowserOutlineMode 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 Outlines and Links</title>
    <link href="styles/webfonts.css" type="text/css" rel="stylesheet">
    <style>
        body {
            font-family: Verdana, sans-serif;
            font-size: 16px;
        }
    </style>
</head>
<body>
    <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="http://www.hiqpdf.com">Visit Website</a>
    <br />
    <a href="#CustomBookmarks">Go To Custom Bookmarks</a>
    <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>

Auto Outlines and Links Demo

In this demo, you learn how to automatically create outlines, HTTP links and internal links in a PDF document, and how to force an HTML element to start on a new PDF page. The demo creates a simple table of contents with internal links to chapters and an HTTP link to the HiQPdf website. For each chapter, an outline entry is added to the document outline, and each chapter is forced to start on a new PDF page using the page-break-before: always style.

Demo Source Code

C#
using HiQPdf.Next;
using HiQPdf_Next_AspNetDemo.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.ComponentModel.DataAnnotations;
using System.IO;

namespace HiQPdf_Next_AspNetDemo.Controllers
{
    public class AutoOutlinesAndLinksController : Controller
    {
        IWebHostEnvironment m_hostingEnvironment;

        public AutoOutlinesAndLinksController(IWebHostEnvironment hostingEnvironment)
        {
            m_hostingEnvironment = hostingEnvironment;
        }

        // GET: AutoOutlinesAndLinks
        public ActionResult Index()
        {
            var model = SetViewModel();

            return View(model);
        }

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

            // Set the serial number received after purchase to use the library in licensed mode; leave it commented for demo mode
            // Licensing.SerialNumber = "your-serial-number";

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

            // create a hierarchy of bookmarks from H1 to H6 tags
            if (model.GenerateOutlines)
            {
                // enable the generation of a PDF outline with bookmarks for H1 to H6 tags
                htmlToPdfConverter.Document.GenerateDocumentOutline = model.GenerateOutlines;

                // optionally enable the outline mode to utilize browser capabilities
                htmlToPdfConverter.Document.UseBrowserOutlineMode = model.UseBrowserOutlineMode;

                // display the bookmarks panel in PDF viewer when the generated PDF is opened
                htmlToPdfConverter.Document.Viewer.PageMode = PdfPageMode.Outlines;
            }

            // convert HTML to PDF
            byte[] pdfBuffer = null;

            if (model.UrlOrHtmlCode == "ConvertUrl")
            {
                // convert URL to a PDF memory buffer
                string url = model.Url;

                pdfBuffer = htmlToPdfConverter.ConvertUrlToMemory(url);
            }
            else
            {
                // convert HTML code
                string htmlCode = model.HtmlCode;
                string baseUrl = model.BaseUrl;

                // convert HTML code to a PDF memory buffer
                pdfBuffer = htmlToPdfConverter.ConvertHtmlToMemory(htmlCode, baseUrl);
            }

            FileResult fileResult = new FileContentResult(pdfBuffer, "application/pdf");
            fileResult.FileDownloadName = "AutoOutlines.pdf";

            return fileResult;
        }

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

            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 - "AutoOutlinesAndLinks".Length);

            model.HtmlCode = System.IO.File.ReadAllText(Path.Combine(contentRootPath, "DemoFiles/Html/AutoOutlines.html"));
            model.BaseUrl = rootUrl + "DemoFiles/Html/";

            return model;
        }
    }
}

See Also