Automatically keeping introduction paragraphs with their content

chrispitude
Posts: 256
Joined: Thu May 02, 2019 2:32 pm

Automatically keeping introduction paragraphs with their content

Post by chrispitude » Wed Oct 07, 2020 3:41 pm

Hi everyone,

We implemented an automatic way keep introduction paragraphs with their content, and I wanted to share it here. (Note that although we specialize @paginate from @outputclass, this method works perfectly with @outputclass too.)

For example,

Code: Select all

<p>The following figure shows blah blah:</p>
<fig>...</fig>

<p>In the preceding figure,</p>
<ul>
  <li>...</li>
  <li>...</li>
</ul>
I created a DITA-OT plugin that adds the following templates to the dita.xsl.html5 extension point:

Code: Select all

  <!-- add @paginate="keep-with-next" for <p> ending in ":" or "," -->
  <xsl:template match="*[contains(@class, ' topic/p ')][matches(., '[,|:]$')][not(tokenize(@paginate, '\s+') = 'keep-with-next')]" priority="20">
    <xsl:call-template name="snps-add-keep-with-next"/>  <!-- will call lower-priority templates -->
  </xsl:template>

  <xsl:template name="snps-add-keep-with-next">
    <xsl:variable name="p" as="node()">
      <xsl:copy select=".">
        <xsl:sequence select="@* except @paginate"/>
        <xsl:attribute name="paginate" select="string-join(('keep-with-next', tokenize(@paginate, '\s+')), ' ')"/>
        <xsl:sequence select="node()"/>
      </xsl:copy>
    </xsl:variable>
    <xsl:apply-templates select="$p"/>
  </xsl:template>
I split the operation into two pieces so it's easy to add more cases in the future. For example, we're also considering adding @paginate="keep-with-next" to standalone code-font keywords that are the first element in a list item, followed by at least one element:

Code: Select all

<li>
  <p><codeph>some_keyword</codeph></p>
  <p>Blah blah blah.</p>
  </li>
<
Our writers already have @paginate="keep-with-next" set on many of these elements, and now they're no longer needed, so I created a refactoring operation to remove them:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  version="2.0">

  <!-- baseline identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- remove @paginate="keep-with-next" for <p> ending in ":" or "," -->
  <xsl:template match="p[matches(., '[,|:]$')][tokenize(@paginate, '\s+') = 'keep-with-next']">
    <xsl:call-template name="snps-remove-keep-with-next"/>
  </xsl:template>

  <xsl:template name="snps-remove-keep-with-next">
    <xsl:variable name="p" as="node()">
      <xsl:copy select=".">
        <xsl:sequence select="@* except @paginate"/>
        <xsl:if test="tokenize(@paginate, ' ')[not(. = 'keep-with-next')]">
          <xsl:attribute name="paginate" select="string-join(tokenize(@paginate, ' ')[not(. = 'keep-with-next')], ' ')"/>
        </xsl:if>
        <xsl:sequence select="node()"/>
      </xsl:copy>
    </xsl:variable>
    <xsl:apply-templates select="$p"/>
  </xsl:template>

</xsl:stylesheet>
And finally, you'll need the following (or similar for @outputclass) for PDF Chemistry to apply the property:

Code: Select all

@media print {
  *[paginate~="keep-with-next"] { page-break-after: avoid; }
}
When I get time, I will package this up as a standalone plugin and refactoring that uses @outputclass instead of @paginate, and provide a link to it in this thread.

Dan
Posts: 466
Joined: Mon Feb 03, 2003 10:56 am

Re: Automatically keeping introduction paragraphs with their content

Post by Dan » Mon Oct 12, 2020 12:43 pm

Hello Chris,
Thank you for sharing your code! So, whenever you have a paragraph that contains punctuation like column or comma, the next content (like images, or other content that may follow it) is kept on the same page with the paragraph. Is a nice example on how powerful is a combination of XSL and CSS!

Many regards,
Dan

chrispitude
Posts: 256
Joined: Thu May 02, 2019 2:32 pm

Re: Automatically keeping introduction paragraphs with their content

Post by chrispitude » Sun Oct 25, 2020 10:24 pm

Hi all,

Here is a generic version of this auto-pagination plugin, along with an Oxygen project that demonstrates it.

pdf_chemistry_auto_paginate.zip
(9.07 KiB) Downloaded 2 times

Note that in our own environment, we use a specialized @paginate attribute rather than @outputclass, as described here:

post54813.html?hilit=paginate%20attribute#p54813

Post Reply