Search code examples
pdfcoldfusioncfmlddx

coldfusion/DDX PDF single page bookmarks


Is there a possibility to generate bookmarks (for DDX table of content) with Coldfusion or DDX without starting a new page?

Coldfusion gives us the possibility to generate pdf-bookmarks with:

<cfdocumentsection name=""></cfdocumentsection>

But this also creates a new page.

All help is welcome.

code:

<cfdocument name="myPdf" format="PDF">
    <cfdocumentsection name="section 1">
        This is section 1
    </cfdocumentsection>
    <cfdocumentsection name="section 2">
        This is section 2
    </cfdocumentsection>
    <cfdocumentsection name="section 3">
        This is section 3
    </cfdocumentsection>
</cfdocument>
<cfprocessingdirective suppressWhitespace="true">
        <cfcontent type="application/pdf" reset="true" variable="#tobinary(myPdf)#"/>
</cfprocessingdirective>

this results in a pdf document with 3 pages and 3 bookmarks


Solution

  • I found the solution, but it's not easy:

    Let's say we have 3 sections of undefined length

        <cfsavecontent variable="section1">
            <p>This is section 1</p>
        </cfsavecontent>
        <cfsavecontent variable="section2">
            <p>This is section 2</p>
        </cfsavecontent>
        <cfsavecontent variable="section3">
            <p>This is section 3</p>
        </cfsavecontent>
    
    <cfset sectionList = 'section1,section2,section3'>
    <cfset bookmarkList = "">
    <cfset content = "">
    <cfset currentPage = 1>
    <cfloop list="#sectionList#" index="i">
        <cfdocument name="infoPdf" format="PDF" bookmark="false">
            <cfdocumentsection>
                <cfoutput>#content#</cfoutput>
                <h2>FakeHeader</h2>
            </cfdocumentsection>
        </cfdocument>
    

    Get the page info to know at what page the content will be

            <cfpdf action="getinfo" name="pdfInfo" source="infoPdf">
            <cfset currentPage = pdfInfo.TotalPages>
            <cfset bookmarkList = listAppend(bookmarkList, currentPage)> 
            <cfset content &= VARIABLES[i]> 
            <cfdocument name="myPdf" format="PDF" bookmark="false">
                <cfdocumentsection>
                    <cfoutput>#content#</cfoutput>
                </cfdocumentsection>
            </cfdocument>
        </cfloop>
        <cfset fileWrite(ExpandPath("test.pdf"),myPdf)>
    

    Define bookmark.xml for DDX manipulation

    <cfxml variable="bookmarks">
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Bookmarks xmlns="http://ns.adobe.com/pdf/bookmarks" version="1.0">
        <cfoutput>
            <cfloop from="1" to="#listlen(sectionList)#" index="i">
                <Bookmark>
                    <Title>#ListGetAt(sectionList,i)#</Title>
                    <Dest>
                      <Fit PageNum="#ListGetAt(bookmarkList,i)-1#"/>
                    </Dest>
                </Bookmark>  
            </cfloop>
        </cfoutput>
    </Bookmarks>
    </cfxml>
    <cfset fileWrite(ExpandPath("/bookmarks.xml"),bookmarks)>
    

    DDX file

    <cfsavecontent variable="myDDX">
        <DDX xmlns="http://ns.adobe.com/DDX/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ns.adobe.com/DDX/1.0/ coldfusion_ddx.xsd">
            <PDF result="Out1">
                <PDF source="test"/>
                <Bookmarks source="inputxml"/>
            </PDF>
            <PDF result="Out">
                <TableOfContents includeInTOC="false" bookmarkTitle="Table of Contents"  maxBookmarkLevel="infinite">   
                    <TableOfContentsEntryPattern applicableLevel="all">
                        <StyledText>
                            <p font-family="Arial" font-size="11pt">
                                <_BookmarkTitle/>
                                <Space/>
                                <Space/>
                                <leader leader-pattern="dotted"/>
                                <Space/>
                                <Space/> 
                                <_BookmarkPageCitation/>
                            </p>
                        </StyledText>
                    </TableOfContentsEntryPattern>
                </TableOfContents>
                <PDF source="Out1"/>
            </PDF>
        </DDX>
    </cfsavecontent>
    

    DDX processing

        <cfset inputStruct = StructNew()>
        <cfset inputStruct.test = 'test.pdf'>
        <cfset inputStruct.inputxml = "bookmarks.xml"/>
        <cfset outputStruct = StructNew()>
        <cfset outputStruct.Out = "CombinedDocument.pdf">
    <cfpdf action="processddx" ddxfile="#myddx#" inputfiles="#inputStruct#" outputfiles="#outputStruct#" name="ddxVar">
    <cfpdf action="read" source="CombinedDocument.pdf" name="resultPdf">
    <cfprocessingdirective suppressWhitespace="true">
        <cfcontent type="application/pdf" reset="true" variable="#tobinary(resultPdf)#"/>
    </cfprocessingdirective>