##+##########################################################################
#
# epubCreator.tsh -- command line tool to create an epub version 3.0
# file from a single text or xhmtml file, an optional cover image and
# a list of 0 or more images
# by Keith Vetter 2014-03-14
# Mods Clif Flynt, 2014-04-01
# Support for multiple text/html files (multiple chapters)
# Support for additional .css file
# Support for filename.epub different from "book title.epub"
# Support for toc.ncx as well as nav.html
# Expanded command line processing
#
# usage: epubCreator \
# -title Title -author 'last, first' -data file1.txt file2.html file3.xhtml...\
# -cover Cover.jpg -images additional Images -css Style.css -html (1/0) \
# -name BookName
#
# -title Title for book
# -author Name of author as last, first
# -data List of data files to include in the text
# -cover An image file for the cover
# -images Additional images that might be reference by text
# -css An optional css file if you want special formatting
# -html 1 or 0 to define whether the input data is already in html format
# -name The name for the .epub file, if different from title
#
package require uuid
package require fileutil
array set EXT {"" "" .png image/png .gif image/gif .jpg image/jpeg
.jpeg image/jpeg .svg image/svg+xml}
proc parseList {list stateVarName {throwError 1}} {
upvar $stateVarName stateArray
set errs ""
foreach arg $list {
if {([string first "-" $arg] == 0) &&
([llength $arg] == 1)} {
set index [string range $arg 1 end]
if {![info exists stateArray($index)]} {
if {$throwError} {
error "No default for ${stateVarName}($index).\nValid fields are [lsort [array names stateArray]]"
} else {
lappend errs "No default for ${stateVarName}($index)"
}
}
set cmd set
} else {
if {[info exists cmd]} {
$cmd stateArray($index) $arg
set cmd lappend
}
}
}
return $errs
}
proc Init {rawname title author cover images} {
global E
set guid [::uuid::uuid generate]
set E(rawname) $rawname
set E(basename) [file tail [file rootname $E(rawname)]]
set E(dirname) [file normalize [file dirname $E(rawname)]]
set E(output,tempdir) [file join [::fileutil::tempdir] "epub_$guid"]
if {$E(name) eq ""} {
set E(output,final) [file join $E(dirname) "$E(basename).epub"]
} else {
set E(output,final) [file join $E(dirname) "$E(name).epub"]
}
set E(epub) EPUB
set E(epub,tempdir) [file join $E(output,tempdir) $E(epub)]
set E(html,name) "$E(basename).xhtml"
set E(html,tempname) [file join $E(epub,tempdir) "$E(html,name)"]
set E(ncx,tempname) [file join $E(epub,tempdir) "toc.ncx"]
set E(opf,name) [file join $E(epub) package.opf]
set E(opf,tempname) [file join $E(output,tempdir) $E(opf,name)]
set E(mimetype) mimetype
set E(mimetype,tempname) [file join $E(output,tempdir) $E(mimetype)]
set E(meta-inf) META-INF
set E(meta-inf,tempdir) [file join $E(output,tempdir) $E(meta-inf)]
set E(meta-inf,tempname) [file join $E(meta-inf,tempdir) container.xml]
set E(nav,name) nav.xhtml
set E(nav,tempname) [file join $E(epub,tempdir) $E(nav,name)]
set E(cover,source) $cover
set E(cover,name) [file tail $cover]
set E(cover,format) $::EXT([file extension $cover])
set E(images) $images
set E(date) [clock format [clock seconds] -gmt 1 -format "%Y-%m-%dT%TZ"]
file mkdir $E(output,tempdir)
file mkdir $E(meta-inf,tempdir)
file mkdir $E(epub,tempdir)
set E(guid) "ebook:$guid"
set E(title) $title
set E(author) $author
if {$E(css) ne ""} {
set E(css,name) $E(css)
set E(css,tempname) [file join $E(epub,tempdir) stylesheet.css]
set E(opf,stylesheet) {
} data
set data "[subst $::HTML_TEMPLATE]" ; list
}
return $data
}
proc BodyToHtml {data} {
global E
set data "[subst $::HTML_TEMPLATE]"
return $data
}
proc MakeOPF {} {
global E
set html_items {}
set image_items {}
set ref_items {}
set opf [subst $::CONTENT_OPF]
if {$E(cover,source) eq ""} {
regsub -all -line {^.*id_cover.*$} $opf "" opf
} else {
file copy $E(cover,source) $E(epub,tempdir)
}
;# Copy any additional images
set image_items ""
for {set i 0} {$i < [llength $E(images)]} {incr i} {
set iname [lindex $E(images) $i]
file copy $iname $E(epub,tempdir)
set tailname [file tail $iname]
set media $::EXT([file extension $iname])
set id "id_image_$i"
set line "
$data