Family Tree Tips ~ Automatic Batch Processing

Introduction

From Family Historian V5 the Plugins feature offers a batch processing solution, and the Improve Website or CD DVD HTML is a published example.

For earlier Versions V3 & V4, this section describes how to use the free AutoHotkey utility.

The AutoHotkey script .ahk file is designed to run in the Project Public folder that contains the \FH CD-DVD\data, \FH CD\data, \FH Website, or \FH Web Page folder.
This is because it relies on the %A_ScriptDir% pointer to the script folder to specify all file paths.

Main Code Section

The head of the AutoHotkey script establishes the environment and calls the processing functions.

#NoEnv					; Recommended for performance and compatibility with future AutoHotkey releases
SendMode Input				; Recommended for new scripts due to its superior speed and reliability
SetWorkingDir %A_ScriptDir%		; Ensures a consistent starting directory

Path := UsePath("FH Web Page")		; Define path subfolder under %A_ScriptDir% as "FH CD\data" or "FH Web Page"

DoCreateJavaScript()			; Create Popup Image Java Script file fhpopup.js in desired Path folder
DoBatchHtmlTidy()			; Batch HTML Tidy all *.html files via Command Prompt in desired Path folder
DoHtmlTextEdits()			; Perform HTML file regular expression text edits in desired Path folder
ExitApp

^!x::
  ExitApp				; Ctrl + Alt + X will abort the script
  Return

UsePath(Folder = "")
{
  ; If Folder exists, then define full Path of construction folder, else return Path value
  Static  Path := ""
  If Not Path
    Path := A_ScriptDir . "\FH Web Page"
  If Folder
    Path := A_ScriptDir . "\" . Folder
  Return Path
}

Return to Introduction.

Create Java Script

The DoCreateJavaScript() function creates the Java Script file fhpopup.js needed for Family Tree Tips ~ Multimedia Image Popups.

Alternatively, it could use FileCopy, fhpopup.js, %Path% if a master fhpopup.js file is kept in the Public folder.

DoCreateJavaScript()
{
  Path := UsePath()
  IfExist, %Path%\fhpopup.js
    FileDelete, %Path%\fhpopup.js		; Delete any existing Java Script
  FileAppend,
  (

  /*
   * Family Historian JavaScript Fullscreen Image Popup Function
   * fhpopup() takes an image filename as its parameter and generates the HTML script to render in the new window
   * fhresize() adjusts the width and height of the image to nearly fill the window depending on their aspect ratios
   */
  function fhpopup(filename)
  {
   openwindow=window.open('','popup','channelmode=yes,fullscreen=yes,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes');
   openwindow.document.write('<html><head><title>popup</title>');
   openwindow.document.write('<link rel="stylesheet" href="fhstyle.css">');
   openwindow.document.write('<script type="text/javascript">');
   openwindow.document.write('function fhresize()');
   openwindow.document.write('{');
   openwindow.document.write(' var window_height = document.body.clientHeight;');
   openwindow.document.write(' var window_width = document.body.clientWidth;');
   openwindow.document.write(' var image_height = document.images[0].height;');
   openwindow.document.write(' var image_width = document.images[0].width;');
   openwindow.document.write(' var height_ratio = image_height / window_height;');
   openwindow.document.write(' var width_ratio = image_width / window_width;');
   openwindow.document.write(' if (height_ratio > width_ratio)');
   openwindow.document.write(' {');
   openwindow.document.write('  document.images[0].style.height = "92`%";');
   openwindow.document.write('  document.images[0].style.width = "auto";');
   openwindow.document.write(' }');
   openwindow.document.write(' else');
   openwindow.document.write(' {');
   openwindow.document.write('  document.images[0].style.height = "auto";');
   openwindow.document.write('  document.images[0].style.width = "98`%";');
   openwindow.document.write(' }');
   openwindow.document.write('}');
   openwindow.document.write('</script>');
   openwindow.document.write('</head><body><center>');
   openwindow.document.write('<form action="javascript:void(0)">');
   openwindow.document.write('<input type="button" value="Close Popup Window" onclick="javascript:self.close()">');
   openwindow.document.write('</form>');
   openwindow.document.write('<img src="'+filename+'" onload="fhresize()" alt="popup" border="1">');
   openwindow.document.write('</center></body></html>');
   openwindow.document.close();
   openwindow.focus();
  }

  ), %Path%\fhpopup.js
}

Return to Introduction.

Batch HTML Tidy

This uses the HTML Tidy Command Prompt utility.

The DoBatchHtmlTidy() function ensures all V3 & V4 HTML files are in consistent format.

The 6th line Send C:{Enter} must use the drive letter on which the Public folder resides.

The 8th line must specify the path to the HTML Tidy utility e.g. "C:\Program Files\Chami\tidy.exe".

DoBatchHtmlTidy()
{
  Path := UsePath()
  Run C:\Windows\System32\cmd.exe	; Defaults to current working drive and directory
  WinWait C:\Windows\System32\cmd.exe
  Send C:{Enter}
  Send cd "%Path%"{Enter}
  Send {Raw} for `%i in (*.html) do "C:\Program Files\Chami\tidy.exe" -f "`%i.log" -modify -indent -wrap 999 "`%i"
  ;   --show-warnings no 	 	This config command inserted in line above inhibits warnings in log file
  Send {Enter}
  TitleOld := "Old"
  TitleNew := "New"
  While TitleOld <> TitleNew		; Loop while Title is changing
  {
    Sleep 1000
    TitleOld := TitleNew
    WinGetTitle, TitleNew
  }
  Send exit{Enter}
  WinWaitClose
  FileDelete, %Path%\*.html.log		; Delete all HTML Tidy batch *.html.log files
}

Return to Introduction.

HTML Text Edits

The DoHtmlTextEdits() function performs HTML file Regular Expression text edits.
The example script is designed to work with Individual Summary Report and Family Group Sheet reports, but may work or be adapted to work for other report types.

The loops scan all the *.html Individual or Family page files, and all other HTML files, line by line.
The 2nd RegExReplace edit implements the Family Tree Tips ~ Text Field URL Hyperlinks feature.
The 3rd RegExReplace edit implements the Family Tree Tips ~ Multimedia Image Popups feature for V3 & V4.
The 1st and 4th to 9th RegExReplace edits simply correct errors in the HTML files of V3 & V4!

Note that the Photo height='150' and Source width='250' thumbnail sizes can be altered to suit your images.
Either height or width can be defined and the other dimension adjusts automatically to maintain aspect ratio.
Note that target='_blank' can be replaced by target='pagename' and all Hyperlinks will open in the same new page.

The final three RegExReplace edits only act on the index.html file and implement the fixes from Family Tree Wizard ~ Step 5 – Create Home Page (V3&V4).
Note that the img width='280' size can be altered to suit your Home Page Picture.

Note every string quote " within Regular Expression strings has to be duplicated in AutoHotkey scripts.
The edits substitute single quotes ' in matched pairs instead of double quotes " wherever possible.
This aids script readability and ensures that repeating the script on processed files does not repeat the edit.

DoHtmlTextEdits()
{
  ; Define thumbnail sizes for Photo and Source images
  PhotoSize := "height='150'"
  SourceSize := "width='250'"

  Path := UsePath()

  Loop, %Path%\*.html
  {
    ImageSize := PhotoSize			; Set thumbnail size for Report Pictures

    FileRead, File, %A_LoopFileFullPath%	; Read file into memory and split into lines
    StringSplit, Line, File, `n
    File := ""

    Loop
    {
      FileLine := Line%A_Index%			; Read each line

      If ( FileLine = "" )
        break					; Escape loop at end of file

      IfInString, FileLine, >Sources<
      {
        ImageSize := SourceSize			; Set thumbnail size for Report Sources
      }

      ; Following edits apply to all "*.html" files

      ; Make >www. hyperlinks open in a new blank tab and remove odd spaces	e.g. ">w ww.
      FileLine := RegExReplace(FileLine
      , """ ?> ?w ?w ?w ?."
      , """ target='_blank'>www.")

      ; Make http:// hyperlinks open in a new blank tab				e.g. <a href="http://...">
      FileLine := RegExReplace(FileLine
      , "<a href=""http://(.+?)"">"
      , "<a href='http://$1' target='_blank'>")

      ; Make image thumbnails open in enlarged popup window			e.g. <td><img src="img9-9-99-99.jpg" width="99" height="99" any></td>
      FileLine := RegExReplace(FileLine
      , "<td><img src=""(img.+?)"" width=""[0-9]{1,4}"" height=""[0-9]{1,4}"" (.+?)></td>"
      , "<td><a href='javascript:void(0)' onclick='fhpopup(""$1"")'><img src=""$1"" " . ImageSize . " $2></a></td>")

      ; Remove extraneous spaces from hyperlinks				e.g. ">ht tp://
      FileLine := RegExReplace(FileLine
      , ">h ?t ?t ?p ?: ?/ ?/ ?"
      , "> http://")

      ; Remove extraneous spaces from hyperlinks				e.g. >http://... ...</a>
      FileLine := RegExReplace(FileLine
      , "> ?http://(.+?) (.+?)</a>"
      , ">http://$1$2</a>")

      ; Remove hyperlink &lt; corruptions					e.g. &lt;/a>
      FileLine := RegExReplace(FileLine
      , "&lt;/"
      , "")

      ; Remove hyperlink &gt; corruptions					e.g. <a&gt;
      FileLine := RegExReplace(FileLine
      , "a&gt;"
      , "")

      ; Correct &amp; related corruptions					e.g. <a href=...&amp;...&amp;</a>;...=... ...</td>
      FileLine := RegExReplace(FileLine
      , "<a href=(.+?)&amp;(.+?)&amp;</a>;(.+?)=(.+?) (.+?)</td>"
      , "<a href=$1&amp;$3=$4$2&amp;$3=$4</a> $5</td>")

      ; Correct &amp; related corruptions					e.g. <a href=...&amp;...&amp;</a>;...=...</td>
      FileLine := RegExReplace(FileLine
      , "<a href=(.+?)&amp;(.+?)&amp;</a>;(.+?)=(.+?)</td>"
      , "<a href=$1&amp;$3=$4$2&amp;$3=$4</a></td>")

      ; Following edits only apply to the "index.html" file

      If ( A_LoopFileName = "index.html" )
      {
        ; Correct pixel width syntax error - remove px				e.g. width="50px"
        FileLine := RegExReplace(FileLine
        , "width=""50px"" "
        , "width='50' ")

        ; Make home page picture popup, and adjust the picture width		e.g. <img src="_h1_filename.jpg" alt="home page picture">
        FileLine := RegExReplace(FileLine
        , "<img src=""_h1_(.+?)"" alt=""home page picture"">"
        , "<a href='javascript:void(0)' onclick='fhpopup(""_h1_$1"")'><img width='280' src='_h1_$1' alt='home page picture'></a>")

        ; Make home page ToC hyperlinks open in a new blank tab			e.g. <td><a href="...">
        FileLine := RegExReplace(FileLine
        , "<td><a href=""(.+?)"">"
        , "<td><a href='$1' target='_blank'>")
      }
      File := File . FileLine . "`n"		; Add processed line to file buffer
    }
    FileDelete, %A_LoopFileFullPath%		; Delete the original file
    FileAppend, %File%, %A_LoopFileFullPath%	; Write file buffer to file
  }
}

Return to Introduction.

Basic User Interface

With AutoHotkey it is fairly easy to add a basic Graphical User Interface (GUI), with a few buttons to invoke each step in the conversion process.

In the Main Code Section above, replace this snippet of code:

DoCreateJavaScript()			; Create Popup Image Java Script file fhpopup.js in desired Path folder
DoBatchHtmlTidy()			; Batch HTML Tidy all *.html files via Command Prompt in desired Path folder
DoHtmlTextEdits()			; Perform HTML file regular expression text edits in desired Path folder
ExitApp

with this GUI script code that defines five buttons:

; GUI		Control	X-pos	Y-pos	Width	, Label
  GUI, +AlwaysOnTop
  GUI, Add,	Button,	X010	Y010	W080	, Everything
  GUI, Add,	Button,	XP+100	YP	WP	, Java Script
  GUI, Add,	Button,	XP+100	YP	WP	, HTML Tidy
  GUI, Add,	Button,	XP+100	YP	WP	, Text Edits
  GUI, Add,	Button,	XP+100	YP	WP	, Quit
  GUI, Show,	X100	Y100			, Automatic Batch Processing
Return

ButtonEverything:
  GUI, Show, Minimize
  DoCreateJavaScript()			; Create Popup Image Java Script file fhpopup.js in desired Path folder
  DoBatchHtmlTidy()			; Batch HTML Tidy all *.html files via Command Prompt in desired Path folder
  DoHtmlTextEdits()			; Perform HTML file regular expression text edits in desired Path folder
  GUI, Show, Restore
Return

ButtonJavaScript:
  GUI, Show, Minimize
  DoCreateJavaScript()			; Create Popup Image Java Script file fhpopup.js in desired Path folder
  GUI, Show, Restore
Return

ButtonHTMLTidy:
  GUI, Show, Minimize
  DoBatchHtmlTidy()			; Batch HTML Tidy all *.html files via Command Prompt in desired Path folder
  GUI, Show, Restore
Return

ButtonTextEdits:
  GUI, Show, Minimize
  DoHtmlTextEdits()			; Perform HTML file regular expression text edits in desired Path folder
  GUI, Show, Restore
Return

ButtonQuit:
GUIClose:
GUIEscape:
  ExitApp				; Quit, Close, Escape will abort the script
Return

Return to Introduction.