summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/tex4ebook
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-07-03 23:26:48 +0000
committerKarl Berry <karl@freefriends.org>2015-07-03 23:26:48 +0000
commitf71a40ca0224f4683054fbb9e1cf9fa26561f829 (patch)
tree62f2c1cda8a9743edfeb4b4634355f9cdf6ef951 /Master/texmf-dist/scripts/tex4ebook
parentf1073f0dfaaeabd2edda00c472a3d814fad132fa (diff)
tex4ebook (29jul15)
git-svn-id: svn://tug.org/texlive/trunk@37751 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/tex4ebook')
-rwxr-xr-xMaster/texmf-dist/scripts/tex4ebook/config-t4e.lua19
-rwxr-xr-xMaster/texmf-dist/scripts/tex4ebook/exec_epub.lua300
-rwxr-xr-xMaster/texmf-dist/scripts/tex4ebook/exec_epub3.lua92
-rwxr-xr-xMaster/texmf-dist/scripts/tex4ebook/exec_mobi.lua20
-rwxr-xr-xMaster/texmf-dist/scripts/tex4ebook/list-fonts.lua145
5 files changed, 576 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/tex4ebook/config-t4e.lua b/Master/texmf-dist/scripts/tex4ebook/config-t4e.lua
new file mode 100755
index 00000000000..9cc6681efec
--- /dev/null
+++ b/Master/texmf-dist/scripts/tex4ebook/config-t4e.lua
@@ -0,0 +1,19 @@
+-- Config file for tex4ebook
+
+-- Font config
+
+Font{
+ name = "cmr",
+ file = "lmroman10-regular.otf",
+ family = "Latin Modern",
+ weight = "normal",
+ style = "normal"
+}
+
+Font{
+ name = "cmmi",
+ file = "lmroman10-italic.otf",
+ family = "Latin Modern",
+ weight = "normal",
+ style = "italic"
+}
diff --git a/Master/texmf-dist/scripts/tex4ebook/exec_epub.lua b/Master/texmf-dist/scripts/tex4ebook/exec_epub.lua
new file mode 100755
index 00000000000..45977c2ee2f
--- /dev/null
+++ b/Master/texmf-dist/scripts/tex4ebook/exec_epub.lua
@@ -0,0 +1,300 @@
+module("exec_epub",package.seeall)
+local lfs = require("lfs")
+local os = require("os")
+local io = require("io")
+--local ebookutils = require("ebookutils")
+local ebookutils = require "mkutils"
+-- font loading doesn't work, font database format changes often
+-- and it is different between TL and Miktex
+-- local load_font = require("list-fonts")
+local outputdir_name="OEBPS"
+local metadir_name = "META-INF"
+local mimetype_name="mimetype"
+outputdir=""
+outputfile=""
+outputfilename=""
+basedir = ""
+tidy = false
+local include_fonts = false
+local metadir=""
+
+
+
+function prepare(params)
+ local randname=tostring(math.random(12000))
+ -- if not ebookutils.file_exists("tex4ht.env") then
+ -- local env_file = kpse.find_file("epub2.env")
+ --print("Local env file: "..env_file)
+ -- ebookutils.copy(env_file,"tex4ht.env")
+ -- end
+ local makedir= function(path)
+ local current = lfs.currentdir()
+ local dir = ebookutils.prepare_path(path .. "/")
+ if type(dir) == "table" then
+ local parts,msg = ebookutils.find_directories(dir)
+ if parts then
+ ebookutils.mkdirectories(parts)
+ end
+ end
+ lfs.chdir(current)
+ end
+ basedir = params.input.."-".. params.format
+ outputdir= basedir.."/"..outputdir_name --"outdir-"..randname --os.tmpdir()
+ makedir(outputdir)
+ -- lfs.mkdir(outputdir)
+ --ebookutils.mkdirectories(ebookutils.prepare_path(outputdir.."/"))
+ metadir = basedir .."/" .. metadir_name --"metadir-"..randname
+ makedir(metadir)
+ --local dd = ebookutils.prepare_path(metadir.."/")
+ --for _,d in pairs(dd) do print("metadir path: "..d) end
+ -- lfs.mkdir(metadir)
+ --local status, msg = ebookutils.mkdirectories(ebookutils.prepare_path(metadir.."/"))
+ --if not status then print("make mmetadir error:" ..msg) end
+ mimetype= basedir .. "/" ..mimetype_name --os.tmpname()
+ print(outputdir)
+ print(mimetype)
+ tidy = params.tidy
+ include_fonts = params.include_fonts
+ params["t4ht_par"] = params["t4ht_par"] -- + "-d"..string.format(params["t4ht_dir_format"],outputdir)
+ return(params)
+end
+
+function run(out,params)
+ --local currentdir=
+ outputfilename=out
+ outputfile = outputfilename..".epub"
+ print("Output file: "..outputfile)
+ --lfs.chdir(metadir)
+ local m= io.open(metadir.."/container.xml","w")
+ m:write([[
+<?xml version="1.0"?>
+<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
+<rootfiles>
+<rootfile full-path="OEBPS/content.opf"
+media-type="application/oebps-package+xml"/>
+</rootfiles>
+</container>
+ ]])
+ m:close()
+ --lfs.chdir("..")
+ m=io.open(mimetype,"w")
+ m:write("application/epub+zip")
+ m:close()
+ local htlatex_run = "${htlatex} ${input} \"${config}${tex4ht_sty_par}\" \"${tex4ht_par}\" \"${t4ht_par}\" \"${latex_par}\"" % params
+ print("Make4ht run")
+ print("-------------------")
+ params.config_file.Make.params = params
+ local mode = params.mode
+ if params.config_file.Make:length() < 1 then
+ if mode == "draft" then
+ params.config_file.Make:htlatex()
+ else
+ params.config_file.Make:htlatex()
+ params.config_file.Make:htlatex()
+ params.config_file.Make:htlatex()
+ end
+ end
+ if #params.config_file.Make.image_patterns > 0 then
+ params["t4ht_par"] = params["t4ht_par"] .." -p"
+ end
+ params.config_file.Make:tex4ht()
+ params.config_file.Make:t4ht()
+ params.config_file.Make:run()
+ print("-------------------")
+ --[[for k,v in pairs(params.config_file.Make) do
+ print(k.. " : "..type(v))
+ end--]]
+ --print(os.execute(htlatex_run))
+end
+
+local mimetypes = {
+ css = "text/css",
+ png = "image/png",
+ jpg = "image/jpeg",
+ gif = "image/gif",
+ svg = "image/svg+xml",
+ html= "application/xhtml+xml",
+ xhtml= "application/xhtml+xml",
+ ncx = "application/x-dtbncx+xml",
+ otf = "application/opentype",
+ ttf = "application/truetype",
+ woff = "application/font-woff",
+ js = "text/javascript"
+}
+
+function make_opf()
+ -- Join files content.opf and content-part2.opf
+ -- make item record for every converted image
+ local lg_item = function(item)
+ -- Find mimetype and make item tag for each converted file in the lg file
+ local fname,ext = item:match("([%a%d%_%-]*)%p([%a%d]*)$")
+ local mimetype = mimetypes[ext] or ""
+ if mimetype == "" then print("Mimetype for "..ext.." is not registered"); return nil end
+ local dir_part = item:split("/")
+ table.remove(dir_part,#dir_part)
+ local id=table.concat(dir_part,"-")..fname.."_"..ext
+ return "<item id='"..id .. "' href='"..item.."' media-type='"..mimetype.."' />",id
+ end
+ local find_all_files= function(s,r)
+ local r = r or "([%a%d%_%-]*)%.([x]?html)"
+ local files = {}
+ for i, ext in s:gmatch(r) do
+ --local i, ext = s:match(r)-- do
+ ext = ext or "true"
+ files[i] = ext
+ end
+ return files
+ end
+ local tidyconf = nil
+ if tidy then
+ tidyconf = kpse.find_file("tidyconf.conf")
+ end
+ --local opf_first_part = outputdir .. "/content.opf"
+ local opf_first_part = "content.opf"
+ local opf_second_part = "content-part2.opf"
+ --local opf_second_part = outputdir .. "/content-part2.opf"
+ if
+ ebookutils.file_exists(opf_first_part) and ebookutils.file_exists(opf_second_part)
+ then
+ local h_first = io.open(opf_first_part,"r")
+ local h_second = io.open(opf_second_part,"r")
+ local opf_complete = {}
+ table.insert(opf_complete,h_first:read("*all"))
+ local used_html = find_all_files(opf_complete[1])
+ local lg_file = ebookutils.parse_lg(outputfilename..".lg")
+ local used_files = lg_file["files"]
+ --[[for f in lfs.dir("./OEBPS") do
+ --table.insert(used_files,f)
+ --used_files[f] = true
+ end--]]
+ local all_html = find_all_files(table.concat(used_files,"\n"))
+ local outside_spine = {}
+ -- This was duplicated code
+ --[[for i, ext in pairs(all_html) do
+ if not used_html[i] then
+ print("Prvni insert: ".. i .."."..ext)
+ local item, id = lg_item(i.."."..ext)
+ table.insert(opf_complete,item)
+ table.insert(outside_spine,id)
+ end
+ end--]]
+ local all_used_files = find_all_files(opf_complete[1],"([%a%d%-%_]+%.[%a%d]+)")
+ local used_paths = {}
+ for _,k in ipairs(lg_file["files"]) do
+ local ext = k:match("%.([%a%d]*)$")
+ local parts = k:split "/"
+ local fn = parts[#parts]
+ local allow_in_spine = {html="",xhtml = "", xml = ""}
+ table.remove(parts,#parts)
+ --table.insert(parts,1,"OEBPS")
+ table.insert(parts,1,outputdir)
+ --print("SSSSS "..fn.." ext .." .. ext)
+ --if string.find("jpg gif png", ext) and not all_used_files[k] then
+ local item,id = lg_item(k)
+ if item then
+ local path = table.concat(parts)
+ if not used_paths[path] then
+ ebookutils.mkdirectories(parts)
+ used_paths[path]=true
+ end
+ if allow_in_spine[ext] and tidy then
+ if tidyconf then
+ print("Tidy: "..k)
+ local run ="tidy -c -w 200 -q -utf8 -m -config " .. tidyconf .." " .. k
+ os.execute(run)
+ else
+ print "Tidy: Cannot load tidyconf.conf"
+ end
+ end
+ ebookutils.copy(k, outputdir .. "/"..k)
+ if not all_used_files[fn] then
+ table.insert(opf_complete,item)
+ if allow_in_spine[ext] then
+ table.insert(outside_spine,id)
+ end
+ end
+ end
+ end
+ for _,f in ipairs(lg_file["images"]) do
+ local f = f.output
+ local p = lg_item(f)
+ ebookutils.copy(f, outputdir .. "/"..f)
+ table.insert(opf_complete,p)
+ end
+ local end_opf = h_second:read("*all")
+ local spine_items = {}
+ for _,i in ipairs(outside_spine) do
+ table.insert(spine_items,
+ '<itemref idref="${idref}" linear="no" />' % {idref=i})
+ end
+ table.insert(opf_complete,end_opf % {spine = table.concat(spine_items,"\n")})
+ h_first:close()
+ h_second:close()
+ h_first = io.open(opf_first_part,"w")
+ local opf_completed = table.concat(opf_complete,"\n")
+ -- poor man's tidy: remove trailing whitespace befora xml tags
+ opf_completed = opf_completed:gsub("[ ]*<","<")
+ h_first:write(opf_completed)
+ h_first:close()
+ os.remove(opf_second_part)
+ --ebookutils.copy(outputfilename ..".css",outputdir.."/")
+ ebookutils.copy(opf_first_part,outputdir.."/"..opf_first_part)
+ --for c,v in pairs(lg_file["fonts"]) do
+ -- print(c, table.concat(v,", "))
+ --end
+ --print(table.concat(opf_complete,"\n"))
+ else
+ print("Missing opf file")
+ end
+ end
+ local function find_zip()
+ if io.popen("zip -v","r"):close() then
+ return "zip"
+ elseif io.popen("miktex-zip -v","r"):close() then
+ return "miktex-zip"
+ end
+ print "It appears you don't have zip command installed. I can't pack the ebook"
+ return "zip"
+ end
+
+ function pack_container()
+ if os.execute("tidy -v") > 0 then
+ print("Warning:\n tidy command seems missing, you need to install it" ..
+ " in order\n to make valid epub file")
+ else
+ print("Tidy ncx "..
+ os.execute("tidy -xml -i -q -utf8 -m " ..
+ outputdir .. "/" .. outputfilename .. ".ncx"))
+ print("Tidy opf "..
+ os.execute("tidy -xml -i -q -utf8 -m " ..
+ outputdir .. "/" .. "content.opf"))
+ end
+ print(mimetype)
+ local zip = find_zip()
+ print("Pack mimetype " .. os.execute("cd "..basedir.." && "..zip.." -q0X "..outputfile .." ".. mimetype_name))
+ print("Pack metadir " .. os.execute("cd "..basedir.." && "..zip.." -qXr9D " .. outputfile.." "..metadir_name))
+ print("Pack outputdir " .. os.execute("cd "..basedir.." && "..zip.." -qXr9D " .. outputfile.." "..outputdir_name))
+ print("Copy generated epub ")
+ ebookutils.cp(basedir .."/"..outputfile, outputfile)
+end
+
+
+ function writeContainer()
+ make_opf()
+ pack_container()
+ end
+ local function deldir(path)
+ for entry in lfs.dir(path) do
+ if entry~="." and entry~=".." then
+ os.remove(path.."/"..entry)
+ end
+ end
+ os.remove(path)
+ --]]
+ end
+
+ function clean()
+ --deldir(outputdir)
+ --deldir(metadir)
+ --os.remove(mimetype)
+ end
diff --git a/Master/texmf-dist/scripts/tex4ebook/exec_epub3.lua b/Master/texmf-dist/scripts/tex4ebook/exec_epub3.lua
new file mode 100755
index 00000000000..55f7f71c309
--- /dev/null
+++ b/Master/texmf-dist/scripts/tex4ebook/exec_epub3.lua
@@ -0,0 +1,92 @@
+module(...,package.seeall)
+local eb = require("exec_epub")
+
+local outputdir = nil
+local input = nil
+function prepare(params)
+ local basedir = params.input.."-".. params.format
+ local outputdir_name="OEBPS"
+ outputdir= basedir.."/"..outputdir_name
+ input = params.input
+ params.packages = params.packages .. "\\Configure{ext}{xhtml}"
+ return eb.prepare(params)
+end
+
+function run(out,params)
+ return eb.run(out, params)
+end
+
+
+local function makeTOC(document)
+ local template = [[
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:epub="http://www.idpf.org/2007/ops"
+>
+<head><title>TOC</title></head>
+<body>
+<nav id="pub-toc" epub:type="toc">
+ <h1>Table of contents</h1>
+ <ol class="toc" hidden="hidden">
+ <li>
+ <a href="${document}">Document</a>
+ </li>
+ </ol>
+</nav>
+</body>
+</html>
+]] % {document=document}
+ return template
+end
+
+local function cleanOPF()
+ -- in epub3, there must be table of contents
+ -- if there is no toc in the document, we must add generic one
+ local opf = "content.opf"
+ local f = io.open(opf,"r")
+ if not f then
+ print("Cannot open "..opf .. " for toc searching")
+ return nil
+ end
+ local content = f:read("*all")
+ f:close()
+ if content:find "properties[%s]*=[%s]*\"[^\"]*nav" then
+ print "TOC nav found"
+ else
+ print "no TOC, using generic one"
+ local pattern = input.."(%..?html)"
+ local ext = content:match(pattern)
+ local inputfile = input .. ext
+ print("Main file name", inputfile)
+ -- write toc file
+ local toc_name = "generic_toc" ..ext
+ local f = io.open(outputdir .. "/" .. toc_name, "w")
+ f:write(makeTOC(inputfile))
+ f:close()
+ -- add toc file to the conten.opf
+ content = content:gsub("<manifest>","<manifest>\n<item id='htmltoc'" ..
+ " properties=\"nav\" media-type=\"application/xhtml+xml\" href=\""..
+ toc_name .."\" />\n")
+ content = content:gsub("<spine([^>]*)>", "<spine%1>\n<itemref idref=\"htmltoc\" linear=\"no\"/>\n")
+ -- remove empty guide element
+ end
+ content = content:gsub("<guide>%s*</guide>","")
+ f = io.open(outputdir .. "/" ..opf,"w")
+ f:write(content)
+ f:close()
+ --makeTOC(inputfile)
+end
+
+
+
+function writeContainer()
+ --local ret = eb.writeContainer()
+ eb.make_opf()
+ cleanOPF()
+ local ret = eb.pack_container()
+ return ret
+end
+
+function clean()
+ return eb.clean()
+end
diff --git a/Master/texmf-dist/scripts/tex4ebook/exec_mobi.lua b/Master/texmf-dist/scripts/tex4ebook/exec_mobi.lua
new file mode 100755
index 00000000000..be9148b5a10
--- /dev/null
+++ b/Master/texmf-dist/scripts/tex4ebook/exec_mobi.lua
@@ -0,0 +1,20 @@
+module(...,package.seeall)
+local eb = require("exec_epub")
+
+function prepare(params)
+ return eb.prepare(params)
+end
+
+function run(out,params)
+ return eb.run(out, params)
+end
+
+function writeContainer()
+ local ret = eb.writeContainer()
+ print("Pack mobi "..os.execute("kindlegen " .. eb.outputfile))
+ return ret
+end
+
+function clean()
+ return eb.clean()
+end
diff --git a/Master/texmf-dist/scripts/tex4ebook/list-fonts.lua b/Master/texmf-dist/scripts/tex4ebook/list-fonts.lua
new file mode 100755
index 00000000000..9acd1665f60
--- /dev/null
+++ b/Master/texmf-dist/scripts/tex4ebook/list-fonts.lua
@@ -0,0 +1,145 @@
+kpse.set_program_name("luatex")
+local function exists(fn)
+ local f = io.open(fn,"r")
+ if f~=nil then io.close(f) return true else return false end
+end
+local function load_fontbase(pathtable)
+ -- path should point to possible location of luaotfload font database
+ -- pathtable should be array of strings
+ -- each path should not end with lua
+
+ local path = pathtable
+ if type(pathtable) =="string" then path = {pathtable} end
+ if #path == 0 then return nil end
+ local currentpath = table.remove(path,1)
+ if exists(currentpath ..".lua") then return require(currentpath)
+ else return load_fontbase(path) end
+end
+
+--local fontbase = require(kpse.expand_var("$TEXMFSYSVAR") .. "/luatex-cache/generic/names/luaotfload-names.lua")
+local sysvar = kpse.expand_var("$TEXMFSYSVAR")
+local var = kpse.expand_var("$TEXMFVAR")
+local namespath = "/luatex-cache/generic/names/"
+local oldnames = "otfl-names"
+local newnames = "luaotfload-names"
+local compose_path = function(path, name) return path .. namespath .. name end
+local fontbase_path = {
+ compose_path(sysvar, newnames),
+ compose_path(var, newnames),
+ compose_path(sysvar, oldnames),
+ compose_path(var,oldnames)
+}
+
+local fontbase = load_fontbase(fontbase_path) or {}
+fontbase.mappings = fontbase.mappings or {}
+-- assert(fontbase, "Cannot load font names")
+
+
+-- [[
+-- This is code for querying the database
+--
+local search = arg[1] or ""
+search = unicode.utf8.lower(search)
+--]]
+local fonts = {}
+for _,record in pairs(fontbase.mappings) do
+ local familyname = record.familyname
+ local styles = fonts[familyname] or {}
+ local sanitized = record.sanitized or record.names
+ local subfamily = sanitized.subfamily --record.sanitized.subfamily or record.names.subfamily
+ styles[subfamily] = record -- We add subfamily as key to prevent duplicates
+ fonts[familyname] = styles
+end
+
+local FontLoader = {}
+
+FontLoader.__index = FontLoader
+
+FontLoader.load_family = function(familyname)
+ local self = setmetatable({},FontLoader)
+ local family = fonts[familyname]
+ --[[ for _, record in pairs(fontbase.mappings) do
+ if record.familyname == familyname then
+ local style = record.sanitized.subfamily
+ family[style] = record
+ end
+ end
+ --]]
+ self.family = family
+ return self
+end
+FontLoader.get_path =function(self,style)
+ local rec = self.family[style]
+ local filename = rec.filename
+ if type(filename) == "table" then
+ filename = filename[1]
+ end
+ return kpse.find_file(filename,'opentype fonts') or kpse.find_file(filename,'truetype fonts')
+end
+
+
+FontLoader.list = function(self)
+ for style,rec in pairs(self.family) do
+ print(style, self:get_path(style))
+ end
+end
+
+
+local FontNames = {}
+FontNames.__index = FontNames
+
+FontNames.new = function()
+ self = setmetatable({},FontNames)
+ self.names = {}
+ return self
+end
+
+FontNames.add_family = function(self,properties)
+ local properties = properties or {}
+ return function(names)
+ local names = names or {}
+ for _,n in pairs(names) do
+ self.names[n] = properties
+ end
+ end
+end
+
+FontNames.list = function(self)
+ for name,prop in pairs(self.names) do
+ local p = {}
+ for k,v in pairs(prop) do
+ table.insert(p,k..'='..v)
+ end
+ print(name, table.concat(p))
+ end
+end
+
+--[[
+local fontnames = {}
+for fontname,_ in pairs(fonts) do
+ local lowername = unicode.utf8.lower(fontname)
+ if lowername:find(search) then
+ table.insert(fontnames, fontname)
+ end
+end
+
+table.sort(fontnames)
+--for fontname, styles in pairs (fonts) do
+for _, name in pairs(fontnames) do
+ local fontname = name
+ local styles = fonts[fontname]
+ local t = {}
+ for n,_ in pairs(styles) do table.insert(t,n) end
+ print(fontname, table.concat(t,', '))
+end
+--]]
+
+local testfont = FontLoader.load_family("math")
+--testfont:list()
+
+local n= FontNames.new()
+n:add_family {type = "serif", name = "LMMono10"} {"cmr"}
+n:add_family {type = "serif", name = "TeXGyreTermes"} {"ts1-qtmr", "ec-qtmr","ec-qtmri"}
+--n:list()
+
+return {FontLoader = FontLoader, FontNames = n}