Page 1 of 1

How do I automatically run a post-processing utility on the PDF file?

Posted: Tue Dec 03, 2019 6:31 am
by chrispitude
I have a post-processing utility that we run on our published PDF files. However, it's cumbersome for our writers to run it manually each time they publish a PDF with PDF Chemistry.

Is there a way to run an external utility automatically as a part of the PDF Chemistry transformation? I don't see an entry for a post-processing command line in the transformation setup, but perhaps there is an Ant parameter or some kind of extension point I can use. The utility simply takes the filename of the PDF file as its only argument, and it modifies the file in-place.

Thanks!

- Chris

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Tue Dec 10, 2019 11:00 am
by julien_lacour
Hello Chris,

You can use a custom build file to call your command line post process using ant. Here is a small example

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="dist">
    <property name="scriptFolder" value="${basedir}\custom\script" />

    <!--The DITA OT default build file-->
    <import file="path\to\dita-ot\build.xml"/>
    <target name="dist">
        <!--Call the DITA OT default target-->
        <antcall target="init"/>
        <exec dir="${scriptFolder}" executable="script.bat">
	        <arg value="fileName"/>
	</exec>
    </target>
</project>
Regards,
Julien

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Wed Dec 11, 2019 7:11 pm
by chrispitude
Hi Julien,

Thank you! I put together the following build_wrapper.xml file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="dist">
    <property name="scriptFolder" value="${basedir}\..\prj\tools\annotate_highlighted_changes" />

    <!--The DITA OT default build file-->
    <import file="C:\Program Files\Oxygen XML Editor 22\frameworks\dita\DITA-OT3.x\build.xml"/>
    <target name="dist">
        <!--Call the DITA OT default target-->
        <antcall target="init"/>
        <exec dir="${scriptFolder}" executable="annotate_highlighted_changes.exe">
                <arg value="fileName"/>
        </exec>
    </target>
</project>
Note that I am actually running a Windows .exe file (it is a perl script, compiled with Strawberry Perl for Windows). However, the transformation fails with the following error:

Code: Select all

Transformation failed. C:\Users\chrispy\Documents\DITA\dita-digital\prj\tools\annotate_highlighted_changes\build_wrapper.xml:10: Execute failed: java.io.IOException: Cannot run program "annotate_highlighted_changes.exe" (in directory "C:\Users\chrispy\Documents\DITA\dita-digital\prj\tools\annotate_highlighted_changes"): CreateProcess error=2, The system cannot find the file specified
In a Windows command window, the concatenation of that path and executable name do invoke the utility:

Code: Select all

C:\Users\chrispy>"C:\Users\chrispy\Documents\DITA\dita-digital\prj\tools\annotate_highlighted_changes\annotate_highlighted_changes.exe"
Usage:
      <pdf_filename>
              PDF file to process
      [--output <new_file_name>]
              Output PDF file to create
              (default is to modify original file in-place)
Is a different build.xml method required to invoke .exe files?

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Thu Dec 12, 2019 10:24 am
by julien_lacour
Hello Chris,

In your case you just need to modify the <exec> declaration:

Code: Select all

<exec dir="${scriptFolder}" executable="annotate_highlighted_changes.exe" resolveexecutable="true">
Here is the ant exec documentation related:
When this attribute is true, the name of the executable is resolved firstly against the project basedir and if that does not exist, against the execution directory if specified. On Unix systems, if you only want to allow execution of commands in the user's path, set this to false. since Ant 1.6
Regards,
Julien

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Thu Dec 12, 2019 3:07 pm
by chrispitude
The executable is now found, thank you!

How can I pass the name of the PDF being generated by the transformation? Currently, <arg/> is hardcoded but this transformation will be used by any number of books. This might be the tricky part...

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Sat Dec 21, 2019 3:13 pm
by chrispitude
I got this working by updating my script to accept a wildcard pattern, then using "${output.dir}/*.pdf" as the filename argument:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="dist">

    <!--The DITA OT default build file-->
    <import file="${dita.dir}\build.xml"/>
    <target name="dist">
        <!--Call the DITA OT default target-->
        <antcall target="init"/>
        <exec dir="../prj/tools/annotate_highlighted_changes" executable="annotate_highlighted_changes.exe" resolveexecutable="true">
	        <arg value="${output.dir}/*.pdf"/>
	</exec>
    </target>
</project>
I still need to do some reading about Ant's exec call to figure out how to replace the relative path to my script with a proper path relative to the Oyxgen project file.

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Mon Jan 06, 2020 3:56 pm
by Radu
Hi,

About this remark:

Code: Select all

I still need to do some reading about Ant's exec call to figure out how to replace the relative path to my script with a proper path relative to the Oyxgen project file.
maybe you can define a property in the build file like "projectBaseDir" and then from the Oxygen transformation scenario pass the "projectBaseDir" as an extra parameter with the value "${pd}" which will be expanded by Oxygen to the project folder before the ANT process is started.

Regards,
Radu

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Wed Jan 08, 2020 3:49 pm
by chrispitude
This worked perfectly - thank you Radu!

Re: How do I automatically run a post-processing utility on the PDF file?

Posted: Fri Jan 15, 2021 6:29 pm
by chrispitude
When I updated my PDF Chemistry parameters to put all PDF files into one place:

"Plugin to leave just the PDF file in the output directory?"
topic22322.html

then my lazy hack of using "*.pdf" to grab the single PDF output file failed. (It matched all of them - oops!)

I tried passing ${outputFile} to my script instead of *.pdf, but for some weird Ant variable/scope/order-of-operations/etc. reason (???), that parameter would not resolve in my build_wrapper.xml.

So, I had to replicate the derivation of ${outputFile} in my wrapper. To be safe, I appended 'MY.' to all of my versions of it. Here's the resulting build_wrapper.xml script:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="dist">

  <!--The DITA OT default build file-->
  <import file="${dita.dir}\build.xml"/>
  <target name="dist">
    <!-- call the DITA-OT default target first -->
    <antcall target="init"/>


    <!-- this is set to Oxygen's ${pd} value -->
    <property name="project.dir" value=""/>


    <!-- we need to re-derive our own copy of ${outputFile}... -->

    <!-- copied from org.dita.base/build_init.xml -->
    <property name="output.dir" location="${dita.dir}/out" />
    <condition property="MY.dita.output.dir" value="${dita.temp.dir}${file.separator}${temp.output.dir.name}" else="${output.dir}">
      <isset property="temp.output.dir.name"/>
    </condition>

    <!-- copied from org.dita.base/build_preprocess2.xml -->
    <property name="MY.uplevels" value=""/>
    <dirname property="MY._dita.map.output.dir" file="${MY.dita.output.dir}/${user.input.file}"/>

    <property name="MY.dita.map.output.dir" location="${MY._dita.map.output.dir}/${MY.uplevels}"/>

    <basename property="MY.dita.input.filename" file="${args.input}"/>
    <pathconvert property="MY.dita.map.filename.root">
      <path path="${MY.dita.input.filename}"/>
      <chainedmapper>
        <mapper type="flatten"/>
        <mapper type="regexp" from="^(.+)(\..+?)$$" to="\1"/>
      </chainedmapper>
    </pathconvert>

    <!-- copied from com.oxygenxml.pdf.css/build.xml -->
    <condition property="MY.outputFile.base" value="${args.output.base}"
      else="${MY.dita.map.filename.root}">
      <isset property="args.output.base"/>
    </condition>
    <condition property="MY.outputFile" value="${outputFile}"
      else="${MY.dita.map.output.dir}/${MY.outputFile.base}.pdf">
      <isset property="outputFile"/>  <!-- had to restructure this fallback for predefined ${outputFile} a bit -->
    </condition>


    <!-- NOW we can apply our own post-processing -->
    <exec dir="${project.dir}/prj/tools/annotate_highlighted_changes" executable="annotate_highlighted_changes.exe" resolveexecutable="true">
      <arg value="--hexcolor"/><arg value="FEFEE1"/>
      <arg value="${MY.outputFile}"/>
    </exec>
  </target>
</project>
Have fun post-processing!