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

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

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

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

julien_lacour
Posts: 200
Joined: Wed Oct 16, 2019 3:47 pm

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

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

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

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

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?

julien_lacour
Posts: 200
Joined: Wed Oct 16, 2019 3:47 pm

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

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 chrispitude Posts: 336 Joined: Thu May 02, 2019 2:32 pm ### Re: How do I automatically run a post-processing utility on the PDF file? 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... chrispitude Posts: 336 Joined: Thu May 02, 2019 2:32 pm ### Re: How do I automatically run a post-processing utility on the PDF file? 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.

Posts: 7579
Joined: Fri Jul 09, 2004 5:18 pm

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

Hi,

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 Radu Coravu <oXygen/> XML Editor http://www.oxygenxml.com chrispitude Posts: 336 Joined: Thu May 02, 2019 2:32 pm ### Re: How do I automatically run a post-processing utility on the PDF file? This worked perfectly - thank you Radu! chrispitude Posts: 336 Joined: Thu May 02, 2019 2:32 pm ### Re: How do I automatically run a post-processing utility on the PDF file? 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!