epub (empty) → 0.0.1
raw patch · 8 files changed
+320/−0 lines, 8 filesdep +Cabaldep +basedep +bytestringsetup-changed
Dependencies added: Cabal, base, bytestring, filepath, ghc, haskell98, old-time, utf8-string, xml, zip-archive
Files
- LICENSE +27/−0
- Setup.hs +2/−0
- epub.cabal +45/−0
- src/Codec/EBook.hs +50/−0
- src/Codec/EBook/OCF.hs +35/−0
- src/Codec/EBook/OPF.hs +76/−0
- src/Codec/EBook/Types.hs +56/−0
- src/xhtml2epub.hs +29/−0
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) Radoslav Dorcik 2009++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ epub.cabal view
@@ -0,0 +1,45 @@+Name: epub+Version: 0.0.1+License: BSD3+License-File: LICENSE+Synopsis: EPUB E-Book construction support library+Author: Radoslav Dorcik <radoslav.dorcik@gmail.com>+Maintainer: radoslav.dorcik@gmail.com+Description: + .+ EPUB E-Book Construction support library, for the details look+ at http://en.wikipedia.org/wiki/EPUB.+ .+Category: Text+Stability: experimental+Build-Type: Simple+Cabal-Version: >= 1.6++Source-Repository head+ type: darcs+ location: http://patch-tag.com/r/dixiecko/epub+ +Library+ Build-Depends: ghc,+ base < 5,+ filepath,+ haskell98,+ old-time,+ utf8-string,+ bytestring, + zip-archive,+ xml,+ Cabal >= 1.5 && < 1.9+ Hs-Source-Dirs: src+ Extensions: CPP, PatternGuards+ Ghc-Options: -Wall -fno-warn-orphans++ Exposed-modules:+ Codec.EBook+ Codec.EBook.Types+ Codec.EBook.OCF+ Codec.EBook.OPF++Executable xhtml2epub+ Hs-Source-Dirs: src+ Main-Is: xhtml2epub.hs
+ src/Codec/EBook.hs view
@@ -0,0 +1,50 @@+-- EBook Types definition++module Codec.EBook (+ module Codec.EBook.Types,+ module Codec.EBook.OPF,+ module Codec.EBook.OCF,+ book2Bin,+ book2Bin',+ book2Arch',+ book2Arch,+ opsMediatype+) +where++import System.Time +import Codec.Archive.Zip+import Codec.EBook.Types+import Codec.EBook.OPF+import Codec.EBook.OCF+import qualified Data.ByteString.Lazy as B++-- EPUB media type+opsMediatype = "application/xhtml+xml"++-- Serialize Book to binary EPUB Format+book2Bin :: Book -> Integer -> B.ByteString+book2Bin book = fromArchive . book2Arch book++-- Serialize Book to binary EPUB Format with current time+book2Bin' :: Book -> IO B.ByteString+book2Bin' book = do + (TOD t _) <- getClockTime + return $ fromArchive (book2Arch book t)++-- Serialize Book to ZIP Archive with current time+book2Arch' :: Book -> IO Archive+book2Arch' book = do+ (TOD t _) <- getClockTime + return $ book2Arch book t++-- Serialize Book to ZIP Archive+book2Arch :: Book -> Integer -> Archive+book2Arch book t = let conXMLFile = containerXMLFile' opfFileName+ opfFileName = "book.opf"+ mimeFile = mimetypeFile+ contFiles = bookFiles book+ allFiles = mimeFile:conXMLFile:contFiles ++ opfFiles book opfFileName+ entries = map (\(n,c) -> toEntry n t c) allFiles+ arch = foldl (\a e -> addEntryToArchive e a) emptyArchive entries+ in arch
+ src/Codec/EBook/OCF.hs view
@@ -0,0 +1,35 @@+-- | Open Container Format 1.0++module Codec.EBook.OCF(+ defaultMediatype,+ defaultMimetype,+ containerXMLFile,+ containerXMLFile',+ mimetypeFile,+ )+where++import Codec.EBook.Types+import Text.XML.Light+import Codec.Archive.Zip+import qualified Data.ByteString.Lazy as B++defaultMediatype = "application/oebps-package+xml"+defaultMimetype = "application/epub+zip"++containerXMLFile' :: FilePath -> (FilePath, B.ByteString)+containerXMLFile' p = containerXMLFile p defaultMediatype++mimetypeFile :: (FilePath, B.ByteString)+mimetypeFile = ("mimetype", str2bstr defaultMimetype)++containerXMLFile :: FilePath -> String -> (FilePath, B.ByteString)+containerXMLFile p m = ("META-INF/container.xml", str2bstr $ ppTopElement contTag)+ where+ contTag = add_attrs contAttrs $ unode "container" rootfilesTag+ contAttrs = [ Attr (unqual "version") "1.0"+ ,Attr (unqual "xmlns") "urn:oasis:names:tc:opendocument:xmlns:container" ] + rootfilesTag = unode "rootfiles" (rootfileTag p m)+ rootfileTag p m = add_attrs (rfAttrs p m) $ unode "rootfile" ()+ rfAttrs p m = [ Attr (unqual "full-path") p+ ,Attr (unqual "media-type") m ]
+ src/Codec/EBook/OPF.hs view
@@ -0,0 +1,76 @@+-- Open Packaging Format 2.0++module Codec.EBook.OPF (+ ncxXML,+ opfXML,+ opfFiles+) +where+import Data.Maybe (fromJust)+import Text.XML.Light+import Codec.EBook.Types+import qualified Data.ByteString.Lazy as B++opfDefaultLang = "en"+opfDefaultCreator = "Unknown"++opfFiles :: Book -> FilePath -> [(FilePath, B.ByteString)] +opfFiles book name = let ncxXMLFile = (ncxFileName,ncxXML book)+ opfXMLFile = (name,opfXML book ncxFileName)+ ncxFileName = "book.ncx"+ in [opfXMLFile, ncxXMLFile]++ncxXML :: Book -> B.ByteString+ncxXML o = str2bstr $ ppTopElement packageT+ where+ packageT= add_attrs packageA $ unode "ncx" nestedT+ packageA = [ Attr (unqual "version") "2005-1"+ ,Attr (unqual "xml:lang") "en"+ ,Attr (unqual "xmlns") "http://www.daisy.org/z3986/2005/ncx/" ]+ nestedT = [ headT, docTitleT, docAuthorT, navMapT ]+ headT = unode "head" $ map (\(n,v) -> add_attrs [ Attr (unqual "name") n,Attr (unqual "content") v] $ unode "meta" ()) metaVals+ metaVals = [ ("dtb:uid",(bookID o))+ ,("dtb:depth","1")+ ,("dtb:totalPageCount","0") + ,("dtb:maxPageNumber","0") ]+ docTitleT = unode "docTitle" $ unode "text" (bookTitle o)+ docAuthorT = unode "docAuthor" $ unode "text" (bookAuthor o)+ numChapterEnt = zip (chapterItems $ bookItems o) [1..]+ navMapT = unode "navMap" (map navPointT numChapterEnt)+ navPointT (e,i) = add_attrs [ Attr (unqual "class") "chapter" + ,Attr (unqual "id") (itemID e)+ ,Attr (unqual "playOrder") (show i) + ] $ unode "navPoint" [ unode "navLabel" $ unode "text" (chapterTitle (fromJust $ itemMetadata e))+ ,add_attr (Attr (unqual "src") (itemFileName e) ) $ unode "content" ()+ ]++opfXML :: Book -> FilePath -> B.ByteString+opfXML o xn = str2bstr $ ppTopElement packageT+ where+ packageT= add_attrs packageA $ unode "package" nestedT+ packageA = [ Attr (unqual "version") "2.0"+ ,Attr (unqual "unique-identifier") "BookId"+ ,Attr (unqual "xmlns") "http://www.idpf.org/2007/opf" ]+ nestedT = [ metadataT, manifestT, spineT ]+ metadataT = add_attrs metadataA $ unode "metadata" [+ unode "dc:title" (bookTitle o),+ unode "dc:language" (bookLang o),+ add_attrs [ Attr (unqual "id") "BookId" + ,Attr (unqual "opf:scheme") "URI" + ] $ unode "dc:identifier" (bookID o)+ ]+ metadataA = [ Attr (unqual "xmlns:dc") "http://purl.org/dc/elements/1.1/" + ,Attr (unqual "xmlns:opf") "http://www.idpf.org/2007/opf"+ ]+ manifestT = unode "manifest" $ map manifestItemT (bookItems o) ++ [ncxItem]+ manifestItemT i = add_attrs [ Attr (unqual "id") (itemID i) + ,Attr (unqual "href") (itemFileName i)+ ,Attr (unqual "media-type") (itemMediaType i) + ] $ unode "item" ()+ ncxItem = add_attrs [ Attr (unqual "id") "ncx" + ,Attr (unqual "href") xn+ ,Attr (unqual "media-type") "application/x-dtbncx+xml" + ] $ unode "item" ()+ spineT = add_attrs [ Attr (unqual "toc") "ncx" ] $ unode "spine" (map spineItemT (bookItems o))+ spineItemT i = add_attrs [ Attr (unqual "idref") (itemID i) ] $ unode "itemref" ()+
+ src/Codec/EBook/Types.hs view
@@ -0,0 +1,56 @@+-- Book Types definition++module Codec.EBook.Types (+ Book(..),+ BookItem(..),+ Metadata(..),+ emptyBook,+ addItem2Book,+ bookFiles,+ chapterItems,+ str2bstr+) +where+import qualified Data.ByteString.Lazy as B+import qualified Data.ByteString.Lazy.Char8 as U+import Control.Arrow ((&&&))++data Book = Book { + bookID :: String,+ bookTitle :: String,+ bookAuthor :: String, + bookLang :: String,+ bookItems :: [BookItem]+ } deriving (Show, Eq, Ord)++data BookItem = BookItem {+ itemID :: String,+ itemFileName :: FilePath,+ itemContent :: B.ByteString,+ itemMediaType :: String,+ itemMetadata :: Maybe Metadata+ } deriving (Show, Eq, Ord)++data Metadata = ChapterMetadata {+ chapterTitle :: String+ } deriving (Show, Eq, Ord)++str2bstr :: String -> B.ByteString+str2bstr = U.pack++emptyBook :: Book+emptyBook = Book "NO ID" "NO TITLE" "NO AUTHOR" "en" []++bookFiles :: Book -> [(FilePath, B.ByteString)]+bookFiles = map (itemFileName &&& itemContent) . bookItems++chapterItems :: [BookItem] -> [BookItem]+chapterItems = filter isChapter+ where+ isChapter (BookItem _ _ _ _ Nothing ) = False+ isChapter _ = True++addItem2Book :: Book -> BookItem -> Book+addItem2Book book item = book { bookItems = newItems }+ where+ newItems = bookItems book ++ [item]
+ src/xhtml2epub.hs view
@@ -0,0 +1,29 @@+import qualified Data.ByteString.Lazy as B+import Codec.EBook+import System.Environment (getArgs)+import System.FilePath+import Data.List (foldl')++main = do+ args <- getArgs+ case args of + (nameOfBook:fileNames) -> do + let book = emptyBook { + bookID = "http://localhost/"++nameOfBook,+ bookAuthor = "xhtml2epub",+ bookTitle = nameOfBook+ }+ items <- mapM loadItems fileNames+ let bookFull = foldl' addItem2Book book items+ let epubFName = nameOfBook++".epub"+ outdata <- book2Bin' bookFull+ B.writeFile epubFName outdata+ putStrLn $ epubFName ++ " constructed."+ _ -> error "Usage: xhtml2epub <name of book> <xhtml file1> [<xhtml file2>,...]"++loadItems :: FilePath -> IO BookItem+loadItems p = do+ c <- B.readFile p+ return (BookItem ("http://localhost/"++np) np c opsMediatype (Just (ChapterMetadata np))) + where+ np = normalise p