epub-tools 1.0.0.1 → 1.1.0
raw patch · 35 files changed
+856/−1104 lines, 35 files
Files
- epub-tools.cabal +3/−26
- src/EpubTools/EpubMeta/Opts.hs +1/−1
- src/EpubTools/EpubName/Author.hs +118/−0
- src/EpubTools/EpubName/Format.hs +397/−0
- src/EpubTools/EpubName/Format/Anonymous.hs +0/−23
- src/EpubTools/EpubName/Format/AuthorBasic.hs +0/−34
- src/EpubTools/EpubName/Format/AuthorDouble.hs +0/−34
- src/EpubTools/EpubName/Format/AuthorSt.hs +0/−23
- src/EpubTools/EpubName/Format/AuthorThird.hs +0/−23
- src/EpubTools/EpubName/Format/MagAeon.hs +0/−45
- src/EpubTools/EpubName/Format/MagAnalog.hs +0/−25
- src/EpubTools/EpubName/Format/MagApex.hs +0/−25
- src/EpubTools/EpubName/Format/MagBcs.hs +0/−25
- src/EpubTools/EpubName/Format/MagChallengingDestiny.hs +0/−25
- src/EpubTools/EpubName/Format/MagClarkesworld.hs +0/−25
- src/EpubTools/EpubName/Format/MagEclipse.hs +0/−45
- src/EpubTools/EpubName/Format/MagFsf.hs +0/−25
- src/EpubTools/EpubName/Format/MagFutureOrbits.hs +0/−26
- src/EpubTools/EpubName/Format/MagGud.hs +0/−25
- src/EpubTools/EpubName/Format/MagInterzone.hs +0/−25
- src/EpubTools/EpubName/Format/MagLightspeed.hs +0/−25
- src/EpubTools/EpubName/Format/MagNameIssue.hs +0/−25
- src/EpubTools/EpubName/Format/MagNemesis.hs +0/−25
- src/EpubTools/EpubName/Format/MagRageMachine.hs +0/−25
- src/EpubTools/EpubName/Format/MagSomethingWicked.hs +0/−25
- src/EpubTools/EpubName/Format/MagUniverse.hs +0/−26
- src/EpubTools/EpubName/Format/SFBestOf.hs +0/−24
- src/EpubTools/EpubName/Format/Util.hs +0/−290
- src/EpubTools/EpubName/Formatters.hs +0/−74
- src/EpubTools/EpubName/Opts.hs +6/−4
- src/EpubTools/EpubName/Util.hs +50/−0
- src/EpubTools/EpubZip/Opts.hs +1/−1
- src/EpubTools/epubname.hs +2/−2
- src/EpubTools/epubzip.hs +2/−2
- testsuite/epubname.hs +276/−76
epub-tools.cabal view
@@ -1,6 +1,6 @@ name: epub-tools cabal-version: >= 1.8-version: 1.0.0.1+version: 1.1.0 build-type: Simple license: BSD3 license-file: LICENSE@@ -41,31 +41,8 @@ build-depends: base >= 3 && < 5, directory, epub-metadata >= 2.2, mtl, regex-compat hs-source-dirs: src- other-modules: EpubTools.EpubName.Format.Anonymous- EpubTools.EpubName.Format.AuthorBasic- EpubTools.EpubName.Format.AuthorDouble- EpubTools.EpubName.Format.AuthorSt- EpubTools.EpubName.Format.AuthorThird- EpubTools.EpubName.Format.MagAeon- EpubTools.EpubName.Format.MagAnalog- EpubTools.EpubName.Format.MagApex- EpubTools.EpubName.Format.MagBcs- EpubTools.EpubName.Format.MagChallengingDestiny- EpubTools.EpubName.Format.MagClarkesworld- EpubTools.EpubName.Format.MagEclipse- EpubTools.EpubName.Format.MagFsf- EpubTools.EpubName.Format.MagFutureOrbits- EpubTools.EpubName.Format.MagGud- EpubTools.EpubName.Format.MagInterzone- EpubTools.EpubName.Format.MagLightspeed- EpubTools.EpubName.Format.MagNameIssue- EpubTools.EpubName.Format.MagNemesis- EpubTools.EpubName.Format.MagRageMachine- EpubTools.EpubName.Format.MagSomethingWicked- EpubTools.EpubName.Format.MagUniverse- EpubTools.EpubName.Format.SFBestOf- EpubTools.EpubName.Formatters- EpubTools.EpubName.Format.Util+ other-modules: EpubTools.EpubName.Author+ EpubTools.EpubName.Format EpubTools.EpubName.Opts EpubTools.EpubName.Util
src/EpubTools/EpubMeta/Opts.hs view
@@ -103,5 +103,5 @@ , "" , "For more information please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm" , ""- , "Version 1.0.0.1 Dino Morelli <dino@ui3.info>"+ , "Version 1.1.0 Dino Morelli <dino@ui3.info>" ]
+ src/EpubTools/EpubName/Author.hs view
@@ -0,0 +1,118 @@+-- Copyright: 2008-2011 Dino Morelli+-- License: BSD3 (see LICENSE)+-- Author: Dino Morelli <dino@ui3.info>++module EpubTools.EpubName.Author+ ( extractAuthors+ , authorMatches+ )+ where++import Codec.Epub.Opf.Package+import Control.Monad+import Data.List ( intercalate )+import Data.Maybe ( isJust )+import Prelude hiding ( last )+import Text.Printf+import Text.Regex++import EpubTools.EpubName.Util+++extractAuthors :: Metadata -> String+extractAuthors = fmtAuthor . separateCombined . justAuthors+ where+ fmtAuthor [] = ""+ fmtAuthor [c] = formatSingleAuthor c+ fmtAuthor cs = (formatMultiAuthors cs) ++ "-"+++separateCombined :: [MetaCreator] -> [MetaCreator]+separateCombined = concatMap separateOne+++separateOne :: MetaCreator -> [MetaCreator]+separateOne c@(MetaCreator r _ di) =+ case (splitRegex (mkRegex " (&|and) ") di) of+ -- If there was only one, leave the file-as alone!+ [_] -> [c]+ -- Otherwise, explode them into separate MetaCreatorS+ ss -> map (MetaCreator r Nothing) ss+++formatSingleAuthor :: MetaCreator -> String++formatSingleAuthor (MetaCreator _ (Just fa) di) = + if ((fa == di) && all (/= ',') fa)+ then formatSingleAuthor $ MetaCreator Nothing Nothing di+ else authorSingle [fa]++formatSingleAuthor (MetaCreator _ _ di) = + authorSingle . reverse . nameParts $ di+++nameParts :: String -> [String]+nameParts s = maybe [] id $ foldl mplus Nothing matches+ where+ matches =+ [ matchRegex (mkRegex "(.*) ([^ ]+)$") s+ , matchRegex (mkRegex "(.*)") s+ ]+++lastName' :: String -> String+lastName' s = maybe "" head $ foldl mplus Nothing matches+ where+ matches =+ [ matchRegex (mkRegex "(.*),.*") s+ , matchRegex (mkRegex ".* (.*)") s+ , matchRegex (mkRegex "(.*)") s+ ]++lastName :: MetaCreator -> String+lastName (MetaCreator _ (Just fa) _ ) = lastName' fa+lastName (MetaCreator _ _ di) = lastName' di+++formatMultiAuthors :: [MetaCreator] -> String+formatMultiAuthors = (intercalate "_") . (map lastName)+++justAuthors :: Metadata -> [MetaCreator]+justAuthors = (filter isAut) . metaCreators+ where+ isAut (MetaCreator (Just "aut") _ _) = True+ isAut (MetaCreator Nothing _ _) = True+ isAut _ = False+++{- A common simple formatter for many book authors+-}+authorSingle :: [String] -> String+authorSingle (last:rest:_) =+ printf "%s%s-" (filterCommon last) (filterCommon rest)+authorSingle [n] = printf "%s-" $ filterCommon n+authorSingle _ = undefined+++{- Throws an error if no author matches the pattern+-}+authorMatches :: Metadata -> String -> EN ()+authorMatches md re = do+ let authorMatches' (MetaCreator _ _ di) =+ matchRegex (mkRegex re) di++ unless (any isJust $ map authorMatches' $ justAuthors md) $+ throwError "Specific author string not found"+++{- Author names with a postfix like II, III, Jr. or Sr.+ FIXME: Is anyone calling this?+-}+{-+authorPostfix :: [String] -> String+authorPostfix (rest:last:postfix:_) =+ printf "%s%s%s-" (filterCommon last) (filterCommon rest)+ (filterCommon postfix)+authorPostfix _ = undefined+-}
+ src/EpubTools/EpubName/Format.hs view
@@ -0,0 +1,397 @@+-- Copyright: 2008-2011 Dino Morelli+-- License: BSD3 (see LICENSE)+-- Author: Dino Morelli <dino@ui3.info>++module EpubTools.EpubName.Format+ ( tryFormatting+ )+ where++import Codec.Epub.Opf.Package+import Control.Monad.Error+import Data.List ( isPrefixOf )+import Text.Printf+import Text.Regex++import EpubTools.EpubName.Author+import EpubTools.EpubName.Opts+import EpubTools.EpubName.Util+++formatters :: [Metadata -> EN (String, [String])]+formatters =+ [ magAeon+ , magAnalog+ , magApex+ , magBcs+ , magBlackStatic+ , magChallengingDestiny+ , magClarkesworld+ , magEclipse+ , magFantasyMag+ , magFsf+ , magFutureOrbits+ , magGud+ , magInterzone+ , magLightspeedDate+ , magLightspeedIssue+ , magNemesis+ , magRageMachine+ , magSomethingWicked+ , magWeirdTales+ , magUniverse+ , compOfTheYear+ , compYearsBest+ , book -- Kind of always want this one last as a catch-all+ ]+++magAeon :: Metadata -> EN (String, [String])+magAeon md = do+ (issue:_) <- extractTitle md "^A[eE]on ([^ ]+)$"+ let title = printf "AeonMagazine%s" (wordNum issue)++ return ("magAeon", [title])+++magAnalog :: Metadata -> EN (String, [String])+magAnalog md = do+ (prefix:month:year:_) <-+ extractTitle md "^(A[^ ]*).*, ([^ ]+) ([0-9]{4})$"++ let title = printf "%sSF%s-%s"+ (filterCommon prefix) year (monthNum month)++ return ("magAnalog", [title])+++magApex :: Metadata -> EN (String, [String])+magApex md = do+ (prefix:issue:_) <- extractTitle md "^(Apex)[^0-9]*([0-9]+)$"+ let title = printf "%sMagazine%03d"+ (filterCommon prefix) (read issue :: Int)++ return ("magApex", [title])+++magBcs :: Metadata -> EN (String, [String])+magBcs md = do+ (prefix:issue:_) <-+ extractTitle md "(Beneath Ceaseless.*) #([0-9]+).*"+ let title = printf "%s_Issue%03d"+ (filterCommon prefix) (read issue :: Int)++ return ("magBcs", [title])+++magBlackStatic :: Metadata -> EN (String, [String])+magBlackStatic md = do+ (prefix:issue:_) <-+ extractTitle md "^(Black Static Horror Magazine)[^0-9]*([0-9]+)$"+ let title = printf "%s%02d" (filterCommon prefix) (read issue :: Int)++ return ("magBlackStatic", [title])+++magChallengingDestiny :: Metadata -> EN (String, [String])+magChallengingDestiny md = do+ (prefix:issue:_) <- extractTitle md "^(Challenging Destiny) #([0-9]+).*"+ let title = printf "%sMagazine%03d"+ (filterCommon prefix) (read issue :: Int)++ return ("magChallengingDestiny", [title])+++magClarkesworld :: Metadata -> EN (String, [String])+magClarkesworld md = do+ (prefix:issue:_) <-+ extractTitle md "^(Clarkesworld)[^0-9]*([0-9]+)$"+ let title = printf "%s%03d" prefix (read issue :: Int)++ return ("magClarkesworld", [title])+++magEclipse :: Metadata -> EN (String, [String])+magEclipse md = do+ (prefix:issue:_) <-+ extractTitle md "^(Eclipse) ([^ ]+)$"+ let title = printf "%s%s" prefix (wordNum issue)++ return ("magEclipse", [title])+++magFantasyMag :: Metadata -> EN (String, [String])+magFantasyMag md = do+ (prefix:issue:_) <-+ extractTitle md "^(Fantasy Magazine)[^0-9]+([0-9]+).*"+ let title = printf "%s%03d" (filterCommon prefix) (read issue :: Int)++ return ("magFantasyMag", [title])+++magFsf :: Metadata -> EN (String, [String])+magFsf md = do+ authorMatches md "Spilogale"++ (month:year:_) <- extractTitle md ".* ([^ ]+) ([0-9]{4})$"+ let title = printf "FantasyScienceFiction%s-%s"+ year (monthNum month)++ return ("magFsf", [title])+++magFutureOrbits :: Metadata -> EN (String, [String])+magFutureOrbits md = do+ (prefix:issue:month:year:_) <- extractTitle md+ "(Future Orbits) Issue ([0-9]+), ([^ ]+) ([0-9]{4})$"+ let title = printf "%sMagazine%02d_%s-%s" (filterCommon prefix)+ (read issue :: Int) year (monthNum month)++ return ("magFutureOrbits", [title])+++magGud :: Metadata -> EN (String, [String])+magGud md = do+ authorMatches md "GUD Magazine Authors"++ (issue:_) <-+ extractTitle md ".* Magazine Issue ([0-9]+) ::.*"+ let title = printf "GUDMagazine%02d" (read issue :: Int)++ return ("magGud", [title])+++magInterzone :: Metadata -> EN (String, [String])+magInterzone md = do+ (prefix:issue:_) <-+ extractTitle md "^(Interzone)[^0-9]*([0-9]+)$"+ let title = printf "%sSFF%03d" prefix (read issue :: Int)++ return ("magInterzone", [title])+++magLightspeedDate :: Metadata -> EN (String, [String])+magLightspeedDate md = do+ (prefix:month:year:_) <-+ extractTitle md "(Lightspeed) Magazine, (.*) (.*)"+ let title = printf "%s%s-%s"+ prefix year (monthNum month)++ return ("magLightspeedDate", [title])+++magLightspeedIssue :: Metadata -> EN (String, [String])+magLightspeedIssue md = do+ (prefix:issue:_) <-+ extractTitle md "(Lightspeed) Magazine Issue (.*)"+ let title = printf "%s%03d" prefix (read issue :: Int)++ return ("magLightspeedIssue", [title])+++magNemesis :: Metadata -> EN (String, [String])+magNemesis md = do+ (prefix:issue:_) <-+ extractTitle md "(Nemesis Mag)azine #([0-9]+).*"+ let title = printf "%s%03d" (filterCommon prefix) (read issue :: Int)++ return ("magNemesis", [title])+++magRageMachine :: Metadata -> EN (String, [String])+magRageMachine md = do+ (prefix:month:year:_) <-+ extractTitle md "(Rage Machine.*)--([^ ]+) ([0-9]{4})$"+ let title = printf "%s_%s-%s"+ (filterCommon prefix) year (monthNum month)++ return ("magRageMachine", [title])+++magSomethingWicked :: Metadata -> EN (String, [String])+magSomethingWicked md = do+ (prefix:issue:_) <- extractTitle md "^(Something Wicked)[^0-9]*([0-9]+)"+ let title = printf "%s%03d"+ (filterCommon prefix) (read issue :: Int)++ return ("magSomethingWicked", [title])+++magUniverse :: Metadata -> EN (String, [String])+magUniverse md = do+ (prefix:vol:num:_) <-+ extractTitle md "^(Jim Baen's Universe)-Vol ([^ ]+) Num ([^ ]+)"+ let title = printf "%sVol%02dNum%02d" (filterCommon prefix)+ (read vol :: Int) (read num :: Int)++ return ("magUniverse", [title])+++magWeirdTales :: Metadata -> EN (String, [String])+magWeirdTales md = do+ (prefix:issue:_) <- extractTitle md "^(Weird Tales)[^0-9]*([0-9]+)$"+ let title = printf "%s%03d"+ (filterCommon prefix) (read issue :: Int)++ return ("magWeirdTales", [title])+++compOfTheYear :: Metadata -> EN (String, [String])+compOfTheYear md = do+ (title:_) <- extractTitle md "(.*of the Year.*)"++ return ("compOfTheYear", [filterCommon title])+++compYearsBest :: Metadata -> EN (String, [String])+compYearsBest md = do+ (title:_) <- extractTitle md "(.*Year's Best.*)"++ return ("compYearsBest", [filterCommon title])+++book :: Metadata -> EN (String, [String])+book md = do+ (title:_) <- extractTitle md "(.*)"+ year <- extractYear md++ return ("book", [extractAuthors md, filterCommon title, year])+++tryFormatting :: FilePath -> Metadata -> EN (String, String)+tryFormatting oldPath md = do+ foldr mplus+ (throwError $ printf "%s [ERROR No formatter found]" oldPath) $+ map (\f -> f md >>= finish md) formatters+++finish :: Metadata -> (String, [String]) -> EN (String, String)+finish md (label, parts) = do+ publisher <- fmap (extractPublisher md) $ asks optPublisher+ return ( label+ , foldr1 (++) (parts ++ [publisher, ".epub"]))+++extractTitle :: Metadata -> String -> EN [String]+extractTitle md re = do+ (MetaTitle _ oldTitle) <- case metaTitles md of+ [] -> throwError "format failed, no title present"+ ts -> return . head $ ts++ case matchRegex (mkRegex re) oldTitle of+ Just matches -> return matches+ Nothing -> throwError $ printf "extract title failed: %s" re+++{- Look for a date tag with event="original-publication" in the+ metadata+-}+extractYear :: Metadata -> EN String+extractYear md = do+ inclY <- asks optYear+ return . maybe "" ('_' :) $+ (foldr mplus Nothing (map (maybeYear inclY) $ metaDates md))++ where+ maybeYear True (MetaDate (Just "original-publication") d) = Just d+ maybeYear _ _ = Nothing+++extractPublisher :: Metadata -> Bool -> String+extractPublisher _ False = ""+extractPublisher md True = maybe "" ('_' :)+ (foldr mplus Nothing (map maybePub $ metaContributors md))++ where+ maybePub (MetaCreator (Just "bkp") (Just fa) _ ) = Just fa+ maybePub _ = Nothing+++{- Convert an English month name (with creative ranges and variations)+ into number form+-}+monthNum :: String -> String+monthNum x+ | isPrefixOf x "January" = "01"+monthNum "January-February" = "01_02"+monthNum "January/February" = "01_02"+monthNum "Jan-Feb" = "01_02"+monthNum "Jan/Feb" = "01_02"+monthNum x+ | isPrefixOf x "February" = "02"+monthNum x+ | isPrefixOf x "March" = "03"+monthNum "March-April" = "03_04"+monthNum "March/April" = "03_04"+monthNum "Mar-Apr" = "03_04"+monthNum "Mar/Apr" = "03_04"+monthNum x+ | isPrefixOf x "April" = "04"+monthNum "April-May" = "04_05"+monthNum "April/May" = "04_05"+monthNum "Apr-May" = "04_05"+monthNum "Apr/May" = "04_05"+monthNum "May" = "05"+monthNum "May-June" = "05_06"+monthNum "May/June" = "05_06"+monthNum "May-Jun" = "05_06"+monthNum "May/Jun" = "05_06"+monthNum x+ | isPrefixOf x "June" = "06"+monthNum "June/July" = "06_07"+monthNum "June-July" = "06_07"+monthNum "Jun-Jul" = "06_07"+monthNum "Jun/Jul" = "06_07"+monthNum x+ | isPrefixOf x "July" = "07"+monthNum "July-August" = "07_08"+monthNum "July/August" = "07_08"+monthNum "Jul-Aug" = "07_08"+monthNum "Jul/Aug" = "07_08"+monthNum x+ | isPrefixOf x "August" = "08"+monthNum "August-September" = "08_09"+monthNum "August/September" = "08_09"+monthNum "Aug-Sep" = "08_09"+monthNum "Aug/Sep" = "08_09"+monthNum x+ | isPrefixOf x "September" = "09"+monthNum "September-October" = "09_10"+monthNum x+ | isPrefixOf x "October" = "10"+monthNum "October-November" = "10_11"+monthNum "October/November" = "10_11"+monthNum "Oct-Nov" = "10_11"+monthNum "Oct/Nov" = "10_11"+monthNum "November-December" = "11_12"+monthNum x+ | isPrefixOf x "November" = "11"+monthNum x+ | isPrefixOf x "December" = "12"+monthNum x = "[ERROR monthNum " ++ x ++ "]"+++{- Convert an English word for a number into number form+-}+wordNum :: String -> String+wordNum "One" = "01"+wordNum "Two" = "02"+wordNum "Three" = "03"+wordNum "Four" = "04"+wordNum "Five" = "05"+wordNum "Six" = "06"+wordNum "Seven" = "07"+wordNum "Eight" = "08"+wordNum "Nine" = "09"+wordNum "Ten" = "10"+wordNum "Eleven" = "11"+wordNum "Twelve" = "12"+wordNum "Thirteen" = "13"+wordNum "Fourteen" = "14"+wordNum "Fifteen" = "15"+wordNum "Sixteen" = "16"+wordNum "Seventeen" = "17"+wordNum "Eighteen" = "18"+wordNum "Nineteen" = "19"+wordNum "Twenty" = "20"+wordNum x = "[ERROR wordNum " ++ x ++ "]"
− src/EpubTools/EpubName/Format/Anonymous.hs
@@ -1,23 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--{-# LANGUAGE FlexibleContexts #-}--module EpubTools.EpubName.Format.Anonymous- ( fmtAnonymous )- where--import Control.Monad.Error--import EpubTools.EpubName.Format.Util- ( format- , authorSingle , titleSimple- )-import EpubTools.EpubName.Util ( Fields )---fmtAnonymous :: (MonadError String m) => Fields -> m (String, String)-fmtAnonymous = format "Anonymous"- "(.*)(Anonymous)" authorSingle- "(.*)" titleSimple
− src/EpubTools/EpubName/Format/AuthorBasic.hs
@@ -1,34 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.AuthorBasic- ( fmtAuthorBasic )- where--import Codec.Epub.Opf.Package.Metadata--import EpubTools.EpubName.Format.Util- ( format- , author, titleSimple- )-import EpubTools.EpubName.Util---fmtAuthorBasic :: Metadata -> EN (String, String)-fmtAuthorBasic = format "AuthorBasic"- ".*" author- "(.*)" titleSimple---{--authorPatterns :: [(String, [String] -> String)]-authorPatterns =- [ ( ".* ([^ ]+) and .* ([^ ]+)", authorDouble )- , ( "(.*)(Anonymous)", authorSingle )- , ( "(.*) ([^ ]+ III)$", authorSingle )- , ( "(.*) ([^ ]+ Jr\\.)$", authorSingle )- , ( "(.*) (St\\. [^ ]+)$", authorSingle )- , ( "(.*) ([^ ]+)$", authorSingle )- ]--}
− src/EpubTools/EpubName/Format/AuthorDouble.hs
@@ -1,34 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.AuthorDouble- ( fmtAuthorDouble )- where--import Codec.Epub.Opf.Package.Metadata-import Data.Maybe ( fromJust )-import Prelude hiding ( last )-import Text.Printf-import Text.Regex--import EpubTools.EpubName.Format.Util ( filterCommon, format, justAuthors, - titleSimple )-import EpubTools.EpubName.Util---fmtAuthorDouble :: Metadata -> EN (String, String)-fmtAuthorDouble = format "AuthorDouble"- ".* and .*" authorDouble- "(.*)" titleSimple---authorDouble :: Metadata -> String-authorDouble = fmtAuthors . extractParts . head . justAuthors- where- extractParts (MetaCreator _ _ di) = fromJust . - matchRegex (mkRegex ".* ([^ ]+) and .* ([^ ]+)") $ di-- fmtAuthors (last1:last2:_) = - printf "%s_%s-" (filterCommon last1) (filterCommon last2)- fmtAuthors _ = undefined
− src/EpubTools/EpubName/Format/AuthorSt.hs
@@ -1,23 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--{-# LANGUAGE FlexibleContexts #-}--module EpubTools.EpubName.Format.AuthorSt- ( fmtAuthorSt )- where--import Control.Monad.Error--import EpubTools.EpubName.Format.Util- ( format- , authorSingle, titleSimple- )-import EpubTools.EpubName.Util ( Fields )---fmtAuthorSt :: (MonadError String m) => Fields -> m (String, String)-fmtAuthorSt = format "AuthorSt"- "(.*) (St\\. [^ ]+)$" authorSingle- "(.*)" titleSimple
− src/EpubTools/EpubName/Format/AuthorThird.hs
@@ -1,23 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--{-# LANGUAGE FlexibleContexts #-}--module EpubTools.EpubName.Format.AuthorThird- ( fmtAuthorThird )- where--import Control.Monad.Error--import EpubTools.EpubName.Format.Util- ( format- , authorPostfix, titleSimple- )-import EpubTools.EpubName.Util ( Fields )---fmtAuthorThird :: (MonadError String m) => Fields -> m (String, String)-fmtAuthorThird = format "AuthorThird"- "(.*) ([^ ]+) (III)$" authorPostfix- "(.*)" titleSimple
− src/EpubTools/EpubName/Format/MagAeon.hs
@@ -1,45 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagAeon- ( fmtMagAeon )- where--import Codec.Epub.Opf.Package.Metadata--import EpubTools.EpubName.Format.Util ( format )-import EpubTools.EpubName.Util---fmtMagAeon :: Metadata -> EN (String, String)-fmtMagAeon = format "MagAeon"- ".* Authors" (const "")- "^A[eE]on ([^ ]+)$" titleMagAeon---titleMagAeon :: String -> [String] -> String-titleMagAeon _ (numWord:_) = "AeonMagazine" ++ (num numWord)- where- num "One" = "01"- num "Two" = "02"- num "Three" = "03"- num "Four" = "04"- num "Five" = "05"- num "Six" = "06"- num "Seven" = "07"- num "Eight" = "08"- num "Nine" = "09"- num "Ten" = "10"- num "Eleven" = "11"- num "Twelve" = "12"- num "Thirteen" = "13"- num "Fourteen" = "14"- num "Fifteen" = "15"- num "Sixteen" = "16"- num "Seventeen" = "17"- num "Eighteen" = "18"- num "Nineteen" = "19"- num "Twenty" = "20"- num x = "[ERROR titleMagAeon " ++ x ++ "]"-titleMagAeon _ _ = undefined
− src/EpubTools/EpubName/Format/MagAnalog.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagAnalog- ( fmtMagAnalog )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format, monthNum )-import EpubTools.EpubName.Util---fmtMagAnalog :: Metadata -> EN (String, String)-fmtMagAnalog = format "MagAnalog"- "Dell Magazine.*" (const "")- "([^ ]*).*, ([^ ]+) ([0-9]{4})$" title---title :: String -> [String] -> String-title _ (prefix:month:year:_) =- printf "%sSF%s-%s" (filterCommon prefix) year (monthNum month)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagApex.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagApex- ( fmtMagApex )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( format )-import EpubTools.EpubName.Util---fmtMagApex :: Metadata -> EN (String, String)-fmtMagApex = format "MagApex"- ".*" (const "")- "^Apex[^0-9]*([0-9]+)$" title---title :: String -> [String] -> String-title _ (issue:_) =- printf "ApexMagazine%03d" (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagBcs.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagBcs- ( fmtMagBcs )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtMagBcs :: Metadata -> EN (String, String)-fmtMagBcs = format "MagBcs"- ".*" (const "")- "(Beneath Ceaseless.*) #([0-9]+).*" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%s_Issue%03d" (filterCommon name) (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagChallengingDestiny.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagChallengingDestiny- ( fmtMagChallengingDestiny )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtMagChallengingDestiny :: Metadata -> EN (String, String)-fmtMagChallengingDestiny = format "MagChallengingDestiny"- "Crystalline Sphere .*" (const "")- "(Challenging Destiny) #([0-9]+).*" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%sMagazine%03d" (filterCommon name) (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagClarkesworld.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagClarkesworld- ( fmtMagClarkesworld )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( format )-import EpubTools.EpubName.Util---fmtMagClarkesworld :: Metadata -> EN (String, String)-fmtMagClarkesworld = format "MagClarkesworld"- ".*" (const "")- "^(Clarkesworld)[^0-9]*([0-9]+)$" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%s%03d" name (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagEclipse.hs
@@ -1,45 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagEclipse- ( fmtMagEclipse )- where--import Codec.Epub.Opf.Package.Metadata--import EpubTools.EpubName.Format.Util ( format )-import EpubTools.EpubName.Util---fmtMagEclipse :: Metadata -> EN (String, String)-fmtMagEclipse = format "MagEclipse"- ".*" (const "")- "^(Eclipse) ([^ ]+)$" titleMagEclipse---titleMagEclipse :: String -> [String] -> String-titleMagEclipse _ (magName:numWord:_) = magName ++ (num numWord)- where- num "One" = "01"- num "Two" = "02"- num "Three" = "03"- num "Four" = "04"- num "Five" = "05"- num "Six" = "06"- num "Seven" = "07"- num "Eight" = "08"- num "Nine" = "09"- num "Ten" = "10"- num "Eleven" = "11"- num "Twelve" = "12"- num "Thirteen" = "13"- num "Fourteen" = "14"- num "Fifteen" = "15"- num "Sixteen" = "16"- num "Seventeen" = "17"- num "Eighteen" = "18"- num "Nineteen" = "19"- num "Twenty" = "20"- num x = "[ERROR titleMagEclipse " ++ x ++ "]"-titleMagEclipse _ _ = undefined
− src/EpubTools/EpubName/Format/MagFsf.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagFsf- ( fmtMagFsf )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( format, monthNum )-import EpubTools.EpubName.Util---fmtMagFsf :: Metadata -> EN (String, String)-fmtMagFsf = format "MagFsf"- "Spilogale.*" (const "")- ".* ([^ ]+) ([0-9]{4})$" title---title :: String -> [String] -> String-title _ (month:year:_) =- printf "FantasyScienceFiction%s-%s" year (monthNum month)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagFutureOrbits.hs
@@ -1,26 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagFutureOrbits- ( fmtMagFutureOrbits )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format, monthNum )-import EpubTools.EpubName.Util---fmtMagFutureOrbits :: Metadata -> EN (String, String)-fmtMagFutureOrbits = format "MagFutureOrbits"- ".*" (const "")- "(Future Orbits) Issue ([0-9]+), ([^ ]+) ([0-9]{4})$" title---title :: String -> [String] -> String-title _ (name:issue:month:year:_) =- printf "%sMagazine%02d_%s-%s"- (filterCommon name) (read issue :: Int) year (monthNum month)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagGud.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagGud- ( fmtMagGud )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( format )-import EpubTools.EpubName.Util---fmtMagGud :: Metadata -> EN (String, String)-fmtMagGud = format "MagGud"- "GUD Magazine Authors" (const "")- ".* Magazine Issue ([0-9]+) ::.*" title---title :: String -> [String] -> String-title _ (issue:_) =- printf "GUDMagazine%02d" (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagInterzone.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagInterzone- ( fmtMagInterzone )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( format )-import EpubTools.EpubName.Util---fmtMagInterzone :: Metadata -> EN (String, String)-fmtMagInterzone = format "MagInterzone"- ".* Authors" (const "")- "^(Interzone)[^0-9]*([0-9]+)$" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%sSFF%d" name (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagLightspeed.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagLightspeed- ( fmtMagLightspeed )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( format, monthNum )-import EpubTools.EpubName.Util---fmtMagLightspeed :: Metadata -> EN (String, String)-fmtMagLightspeed = format "MagInterzone"- ".*" (const "")- "(Lightspeed) Magazine, (.*) (.*)" title---title :: String -> [String] -> String-title _ (name:month:year:_) =- printf "%s%s-%s" name year (monthNum month)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagNameIssue.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagNameIssue- ( fmtMagNameIssue )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtMagNameIssue :: Metadata -> EN (String, String)-fmtMagNameIssue = format "MagNameIssue"- ".* Authors" (const "")- "(.*) #([0-9]+).*" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%s%02d" (filterCommon name) (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagNemesis.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagNemesis- ( fmtMagNemesis )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtMagNemesis :: Metadata -> EN (String, String)-fmtMagNemesis = format "MagNemesis"- "Stephen Adams" (const "")- "(Nemesis Mag)azine #([0-9]+).*" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%s%03d" (filterCommon name) (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagRageMachine.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagRageMachine- ( fmtMagRageMachine )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format, monthNum )-import EpubTools.EpubName.Util---fmtMagRageMachine :: Metadata -> EN (String, String)-fmtMagRageMachine = format "MagRageMachine"- ".*" (const "")- "(Rage Machine.*)--([^ ]+) ([0-9]{4})$" title---title :: String -> [String] -> String-title _ (name:month:year:_) =- printf "%s_%s-%s" (filterCommon name) year (monthNum month)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagSomethingWicked.hs
@@ -1,25 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagSomethingWicked- ( fmtMagSomethingWicked )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtMagSomethingWicked :: Metadata -> EN (String, String)-fmtMagSomethingWicked = format "MagSomethingWicked"- ".* Authors" (const "")- "(Something Wicked).* #([0-9]+).*" title---title :: String -> [String] -> String-title _ (name:issue:_) =- printf "%sMagazine%02d" (filterCommon name) (read issue :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/MagUniverse.hs
@@ -1,26 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.MagUniverse- ( fmtMagUniverse )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtMagUniverse :: Metadata -> EN (String, String)-fmtMagUniverse = format "MagUniverse"- ".*" (const "")- "^(Jim Baen's Universe)-Vol ([^ ]+) Num ([^ ]+)" title---title :: String -> [String] -> String-title _ (name:vol:num:_) =- printf "%sVol%02dNum%02d" (filterCommon name) (read vol :: Int) - (read num :: Int)-title _ _ = undefined
− src/EpubTools/EpubName/Format/SFBestOf.hs
@@ -1,24 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.SFBestOf- ( fmtSFBestOf )- where--import Codec.Epub.Opf.Package.Metadata-import Text.Printf--import EpubTools.EpubName.Format.Util ( filterCommon, format )-import EpubTools.EpubName.Util---fmtSFBestOf :: Metadata -> EN (String, String)-fmtSFBestOf = format "SFBestOf"- "Rich Horton.*" (const "")- "(.*)" title---title :: String -> [String] -> String-title year (name:_) = printf "%s%s" (filterCommon name) year-title _ _ = undefined
− src/EpubTools/EpubName/Format/Util.hs
@@ -1,290 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Format.Util- ( filterCommon, format- , author- , authorSingle, authorPostfix- , justAuthors- , titleSimple- , monthNum )- where--import Codec.Epub.Opf.Package-import Control.Monad.Error-import Data.Char-import Data.List ( foldl', intercalate, isPrefixOf )-import Data.Maybe ( fromJust )---import Debug.Trace-import Prelude hiding ( last )-import Text.Printf-import Text.Regex--import EpubTools.EpubName.Opts-import EpubTools.EpubName.Util----{- Convenience function to make a regex replacer for a given pattern - and replacement string. Helps by doing the 'flip' of str and rpl- so you can partial eval.--}-repl :: String -> String -> String -> String-repl re rpl str = subRegex (mkRegex re) str rpl---{- Transforms a string like this:- "the quick brown McCheeseburger" -> "TheQuickBrownMccheeseburger"--}-capFirstAndDeSpace :: String -> String-capFirstAndDeSpace s = concat $ map capFirst $ words s- where- capFirst (first:rest) = (toUpper first) : (map toLower rest)- capFirst _ = undefined---{- A set of common string filters that apply to any and all parts- of every single string we process in this project.--}-commonFilters :: [(String -> String)]-commonFilters =- [ repl "[',\\?();#’]" ""- , repl "\\." " "- , repl ":" "_"- , filter (/= '"')- , repl "]" ""- , repl "\\*" ""- , repl "!" ""- , repl "-" " "- , repl "\\[" "_ "- -- Decided that I like the article included in titles- --, repl "^The " ""- , repl "&" " And "- , capFirstAndDeSpace- ]---{- Utility function to apply the above commonFilters to a string,- giving you back the transformed string--}-filterCommon :: String -> String-filterCommon s = foldl' (flip id) s commonFilters---{- Convert an English month name (with creative ranges and variations)- into number form--}-monthNum :: String -> String-monthNum x- | isPrefixOf x "January" = "01"-monthNum "January-February" = "01_02"-monthNum "January/February" = "01_02"-monthNum "Jan-Feb" = "01_02"-monthNum "Jan/Feb" = "01_02"-monthNum x- | isPrefixOf x "February" = "02"-monthNum x- | isPrefixOf x "March" = "03"-monthNum "March-April" = "03_04"-monthNum "March/April" = "03_04"-monthNum "Mar-Apr" = "03_04"-monthNum "Mar/Apr" = "03_04"-monthNum x- | isPrefixOf x "April" = "04"-monthNum "April-May" = "04_05"-monthNum "April/May" = "04_05"-monthNum "Apr-May" = "04_05"-monthNum "Apr/May" = "04_05"-monthNum "May" = "05"-monthNum "May-June" = "05_06"-monthNum "May/June" = "05_06"-monthNum "May-Jun" = "05_06"-monthNum "May/Jun" = "05_06"-monthNum x- | isPrefixOf x "June" = "06"-monthNum "June/July" = "06_07"-monthNum "June-July" = "06_07"-monthNum "Jun-Jul" = "06_07"-monthNum "Jun/Jul" = "06_07"-monthNum x- | isPrefixOf x "July" = "07"-monthNum "July-August" = "07_08"-monthNum "July/August" = "07_08"-monthNum "Jul-Aug" = "07_08"-monthNum "Jul/Aug" = "07_08"-monthNum x- | isPrefixOf x "August" = "08"-monthNum "August-September" = "08_09"-monthNum "August/September" = "08_09"-monthNum "Aug-Sep" = "08_09"-monthNum "Aug/Sep" = "08_09"-monthNum x- | isPrefixOf x "September" = "09"-monthNum "September-October" = "09_10"-monthNum x- | isPrefixOf x "October" = "10"-monthNum "October-November" = "10_11"-monthNum "October/November" = "10_11"-monthNum "Oct-Nov" = "10_11"-monthNum "Oct/Nov" = "10_11"-monthNum "November-December" = "11_12"-monthNum x- | isPrefixOf x "November" = "11"-monthNum x- | isPrefixOf x "December" = "12"-monthNum x = "[ERROR monthNum " ++ x ++ "]"---formatAuthor- :: String- -> (Metadata -> String)- -> Metadata- -> EN String-formatAuthor re f md =- maybe (throwError "formatAuthor failed")- (const (return . f $ md)) (tryPats $ justAuthors md)-- where- justAuthorStrings = map (\(MetaCreator _ _ n) -> n)-- match = matchRegex (mkRegex re)-- tryPats [] = Just [] -- Special case of no authors at all- tryPats as = foldr mplus Nothing- ((map match) . justAuthorStrings $ as)---formatTitle - :: String- -> (String -> [String] -> String)- -> String- -> String- -> EN String-formatTitle re f year s = case matchRegex (mkRegex re) s of- Just xs -> return $ f year xs- Nothing -> throwError "formatTitle failed"---{- Look for a date tag with event="original-publication" in the- metadata--}-extractYear :: Metadata -> EN String-extractYear md = do- inclY <- asks optYear- return . maybe "" ('_' :) $- (foldr mplus Nothing (map (maybeYear inclY) $ metaDates md))-- where- maybeYear True (MetaDate (Just "original-publication") d) = Just d- maybeYear _ _ = Nothing---extractPublisher :: Metadata -> Bool -> String-extractPublisher _ False = ""-extractPublisher md True = maybe "" ('_' :)- (foldr mplus Nothing (map maybePub $ metaContributors md))-- where- maybePub (MetaCreator (Just "bkp") (Just fa) _ ) = Just fa- maybePub _ = Nothing---{- This is the main work performing function that's called by every - formatter. It expects to see a regexp pattern and format function - for both author and title parts of the book info. And then the map - of fields from a book.- If the pattern matches, the resulting list of match results is sent - to the supplied format function. If any of this fails, the entire - action throws.--}-format- :: String- -> String- -> (Metadata -> String)- -> String- -> (String -> [String] -> String)- -> Metadata- -> EN (String, String)-format label authorPat authorFmt titlePat titleFmt md = do- newAuthor <- formatAuthor authorPat authorFmt md- --trace newAuthor (return ())-- (MetaTitle _ oldTitle) <- case metaTitles md of- [] -> throwError "format failed, no title present"- ts -> return . head $ ts- year <- extractYear md- newTitle <- formatTitle titlePat titleFmt year oldTitle-- publisher <- fmap (extractPublisher md) $ asks optPublisher-- return- ( label- , printf "%s%s%s.epub" newAuthor newTitle publisher- )---formatSingleAuthor :: MetaCreator -> String--formatSingleAuthor (MetaCreator _ (Just fa) di) = - if ((fa == di) && all (/= ',') fa)- then formatSingleAuthor $ MetaCreator Nothing Nothing di- else authorSingle [fa]--formatSingleAuthor (MetaCreator _ _ di) = - authorSingle . reverse $ parts- where- parts = fromJust .- (matchRegex (mkRegex "(.*) ([^ ]+)$")) $ di---lastName :: MetaCreator -> String-lastName (MetaCreator _ (Just fa) _ ) = head . fromJust .- (matchRegex (mkRegex "(.*),.*")) $ fa-lastName (MetaCreator _ _ di) = head . fromJust .- (matchRegex (mkRegex ".* (.*)")) $ di---formatMultiAuthors :: [MetaCreator] -> String-formatMultiAuthors = (intercalate "_") . (map lastName)---justAuthors :: Metadata -> [MetaCreator]-justAuthors = (filter isAut) . metaCreators- where- isAut (MetaCreator (Just "aut") _ _) = True- isAut (MetaCreator Nothing _ _) = True- isAut _ = False---author :: Metadata -> String-author = fmtAuthor . justAuthors- where- fmtAuthor [c] = formatSingleAuthor c- fmtAuthor cs = (formatMultiAuthors cs) ++ "-"---{- A common simple formatter for many book authors--}-authorSingle :: [String] -> String-authorSingle (last:rest:_) =- printf "%s%s-" (filterCommon last) (filterCommon rest)-authorSingle [n] = printf "%s-" $ filterCommon n---authorSingle x = show x-authorSingle _ = undefined---{- Author names with a postfix like II, III, Jr. or Sr.--}-authorPostfix :: [String] -> String-authorPostfix (rest:last:postfix:_) =- printf "%s%s%s-" (filterCommon last) (filterCommon rest)- (filterCommon postfix)-authorPostfix _ = undefined---{- A common simple formatter for many book titles. Handles year too.--}-titleSimple :: String -> [String] -> String-titleSimple year (old:_) = printf "%s%s" (filterCommon old) year-titleSimple _ _ = undefined
− src/EpubTools/EpubName/Formatters.hs
@@ -1,74 +0,0 @@--- Copyright: 2008-2011 Dino Morelli--- License: BSD3 (see LICENSE)--- Author: Dino Morelli <dino@ui3.info>--module EpubTools.EpubName.Formatters- ( tryFormatting )- where--import Codec.Epub.Opf.Package.Metadata-import Control.Monad-import Text.Printf----import EpubTools.EpubName.Format.Anonymous-import EpubTools.EpubName.Format.AuthorBasic-import EpubTools.EpubName.Format.AuthorDouble---import EpubTools.EpubName.Format.AuthorSt---import EpubTools.EpubName.Format.AuthorThird-import EpubTools.EpubName.Format.MagAeon-import EpubTools.EpubName.Format.MagAnalog-import EpubTools.EpubName.Format.MagApex-import EpubTools.EpubName.Format.MagBcs-import EpubTools.EpubName.Format.MagChallengingDestiny-import EpubTools.EpubName.Format.MagClarkesworld-import EpubTools.EpubName.Format.MagEclipse-import EpubTools.EpubName.Format.MagFsf-import EpubTools.EpubName.Format.MagFutureOrbits-import EpubTools.EpubName.Format.MagGud-import EpubTools.EpubName.Format.MagInterzone-import EpubTools.EpubName.Format.MagLightspeed-import EpubTools.EpubName.Format.MagNameIssue-import EpubTools.EpubName.Format.MagNemesis-import EpubTools.EpubName.Format.MagRageMachine-import EpubTools.EpubName.Format.MagSomethingWicked-import EpubTools.EpubName.Format.MagUniverse-import EpubTools.EpubName.Format.SFBestOf-import EpubTools.EpubName.Util---formatters :: [Metadata -> EN (String, String)]-formatters =-{-- , fmtAnonymous- , fmtAuthorThird- , fmtAuthorSt--}- [ fmtMagAnalog- , fmtMagNemesis- , fmtMagAeon- , fmtMagEclipse- , fmtMagChallengingDestiny- , fmtMagClarkesworld- , fmtMagGud- , fmtMagInterzone- , fmtMagLightspeed- , fmtMagSomethingWicked- , fmtMagRageMachine- , fmtMagFsf- , fmtMagFutureOrbits- , fmtMagBcs- , fmtMagApex- , fmtMagNameIssue- , fmtMagUniverse- , fmtSFBestOf- , fmtAuthorDouble-- , fmtAuthorBasic- ]---tryFormatting :: (FilePath, Metadata) -> EN (String, String)-tryFormatting (oldPath, md) = do- foldr mplus - (throwError $ printf "%s [ERROR No formatter found]" oldPath) $- map (\f -> f md) formatters
src/EpubTools/EpubName/Opts.hs view
@@ -81,8 +81,8 @@ ] footer = init $ unlines [ "Verbosity levels:"- , " 1 - Include which formatter processed the file"- , " 2 - Include the OPF Package and Metadata info"+ , " 1 - Include which formatter processed the file"+ , " 2 - Include the OPF Package and Metadata info" , "" , "Exit codes:" , " 0 - success"@@ -91,6 +91,8 @@ , "" , "Book names are constructed by examining parts of the OPF Package metadata such as the title, creators, contributors and dates." , ""+ , "Strings from the OPF metadata fields are stripped of punctuation, CamelCased and stripped of spaces. Resulting file names look like this:"+ , "" , "For books with a single author:" , " LastFirst[Middle]-TitleText[_year][_publisher].epub" , ""@@ -102,7 +104,7 @@ , "" , "Only creator tags with either a role attribute of 'aut' or no role at all are considered authors. If a file-as attribute is present, this will be the preferred string. If not, the program tries to do some intelligent parsing of the name." , ""- , "The date is taken from the first date tag with an event attribute of 'original-publication', if present. The OPF spec is a little thin on this. I noticed frequent use of this attribute in books, and so went with that."+ , "The publication year is taken from the first date tag with an event attribute of 'original-publication', if present. The OPF spec is a little thin on this. I noticed frequent use of this attribute in books, and so went with that." , "" , "Publisher: I wanted to provide a way to have multiple copies of the same book produced by different publishers and name them sort-of unambiguously. I came up with the idea of expecting a contributor tag with role attribute of 'bkp' (so far, this is fairly normal). And then use a file-as attribute on that tag to contain a small string to be used in the filename. The idea here is short and sweet for the file-as." , ""@@ -110,5 +112,5 @@ , "" , "For more information please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm" , ""- , "Version 1.0.0.1 Dino Morelli <dino@ui3.info>"+ , "Version 1.1.0 Dino Morelli <dino@ui3.info>" ]
src/EpubTools/EpubName/Util.hs view
@@ -6,11 +6,15 @@ ( EN , runEN , throwError , asks+ , filterCommon ) where import Control.Monad.Error import Control.Monad.Reader+import Data.Char+import Data.List ( foldl' )+import Text.Regex import EpubTools.EpubName.Opts @@ -19,3 +23,49 @@ runEN :: Options -> EN a -> IO (Either String a) runEN env ev = runErrorT $ runReaderT ev env+++{- Convenience function to make a regex replacer for a given pattern + and replacement string. Helps by doing the 'flip' of str and rpl+ so you can partial eval.+-}+repl :: String -> String -> String -> String+repl re rpl str = subRegex (mkRegex re) str rpl+++{- Transforms a string like this:+ "the quick brown McCheeseburger" -> "TheQuickBrownMccheeseburger"+-}+capFirstAndDeSpace :: String -> String+capFirstAndDeSpace s = concat $ map capFirst $ words s+ where+ capFirst (first:rest) = (toUpper first) : (map toLower rest)+ capFirst _ = undefined+++{- A set of common string filters that apply to any and all parts+ of every single string we process in this project.+-}+commonFilters :: [(String -> String)]+commonFilters =+ [ repl "[',\\?();#’]" ""+ , repl "\\." " "+ , repl ":" "_"+ , filter (/= '"')+ , repl "]" ""+ , repl "\\*" ""+ , repl "!" ""+ , repl "-" " "+ , repl "\\[" "_ "+ -- Decided that I like the article included in titles+ --, repl "^The " ""+ , repl "&" " And "+ , capFirstAndDeSpace+ ]+++{- Utility function to apply the above commonFilters to a string,+ giving you back the transformed string+-}+filterCommon :: String -> String+filterCommon s = foldl' (flip id) s commonFilters
src/EpubTools/EpubZip/Opts.hs view
@@ -68,5 +68,5 @@ , "" , "For more information please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm" , ""- , "Version 1.0.0.1 Dino Morelli <dino@ui3.info>"+ , "Version 1.1.0 Dino Morelli <dino@ui3.info>" ]
src/EpubTools/epubname.hs view
@@ -15,7 +15,7 @@ ) import Text.Printf -import EpubTools.EpubName.Formatters ( tryFormatting )+import EpubTools.EpubName.Format ( tryFormatting ) import EpubTools.EpubName.Opts ( Options (..), parseOpts, usageText ) import EpubTools.EpubName.Util @@ -50,7 +50,7 @@ result <- runEN opts $ do pkg <- parseEpubOpf oldPath let md = opMeta pkg- (fmtUsed, newPath) <- tryFormatting (oldPath, md)+ (fmtUsed, newPath) <- tryFormatting oldPath md when (not $ optOverwrite opts) $ do fileExists <- liftIO $ doesFileExist newPath
src/EpubTools/epubzip.hs view
@@ -13,7 +13,7 @@ import System.FilePath import Text.Printf -import EpubTools.EpubName.Formatters ( tryFormatting )+import EpubTools.EpubName.Format ( tryFormatting ) import qualified EpubTools.EpubName.Opts as EN import EpubTools.EpubName.Util ( runEN ) import EpubTools.EpubZip.Opts@@ -39,7 +39,7 @@ (_, contents) <- opfContentsFromDir "." parseXmlToOpf contents (_, newPath) <- tryFormatting- ("CURRENT DIRECTORY", opMeta package)+ "CURRENT DIRECTORY" $ opMeta package return $ inputPath </> newPath else return . Right $ inputPath
testsuite/epubname.hs view
@@ -10,7 +10,7 @@ import Test.HUnit ( Counts (..), Test (..), assertEqual, runTestTT ) import Test.HUnit.Base ( Assertion ) -import EpubTools.EpubName.Formatters ( tryFormatting )+import EpubTools.EpubName.Format ( tryFormatting ) import EpubTools.EpubName.Opts import EpubTools.EpubName.Util @@ -33,12 +33,15 @@ tests :: Test tests = TestList [ testAuthorMinimal+ , testAuthorOneName , testAuthorRole , testAuthorFileas , testAuthorFull- , testAuthorDoubleAnd+ , testAuthorSeveral+ , testSeveralAuthors , testNoAuthor- , testNoAuthorPubDate+ , testCreatorsNoAuthor+ , testCreatorsNoAuthorPubDate , testCapsTitle , testColon , testBracketTitle@@ -52,20 +55,25 @@ , testMagApexShort , testChallengingDestinyShort , testChallengingDestinyLong- , testChallengingDestinyPub , testAnalog , testAsimovs+ , testFantasyMagazine , testFsfShort , testFsfLong+ , testFsfAmpersand , testMagFutureOrbits , testGudShort , testGudLong+ , testGudVeryLong , testInterzoneShort , testInterzoneLong , testNemesisShort , testNemesisLong , testMagSomethingWicked+ , testMagSomethingWickedMonth , testSFBestOf+ , testBestSF+ , testYearsBest , testMagBlackStatic , testRageMachineMag , testEclipseMag@@ -75,13 +83,16 @@ , testBkpMissing , testMagUniverse , testMagClarkesworld+ , testLightspeedDate+ , testLightspeedIssue+ , testMagWeirdTales ] assertNewNameOpts :: Options -> String -> Metadata -> (String, String) -> Assertion assertNewNameOpts opts desc meta expected = do- result <- runEN opts $ tryFormatting ("", meta)+ result <- runEN opts $ tryFormatting "" meta let actual = either (\em -> ("NO FORMATTER", em)) id result assertEqual desc expected actual @@ -99,11 +110,25 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick.epub" ) +testAuthorOneName :: Test+testAuthorOneName = TestCase $+ assertNewName "author is a single word" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator Nothing Nothing "Melville"]+ , metaTitles = [MetaTitle Nothing "Moby Dick"]+ }+ expected =+ ( "book"+ , "Melville-MobyDick.epub"+ )++ testAuthorRole :: Test testAuthorRole = TestCase $ assertNewName "author with role" meta expected@@ -114,7 +139,7 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick.epub" ) @@ -130,7 +155,7 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick.epub" ) @@ -146,16 +171,53 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick.epub" ) +testAuthorSeveral :: Test+testAuthorSeveral = TestCase $+ assertNewName "several authors" meta expected+ where+ meta = emptyMetadata+ { metaCreators =+ [ MetaCreator (Just "aut") Nothing+ "James Patrick Kelly"+ , MetaCreator (Just "aut") (Just "Kessel, John")+ "John Kessel"+ , MetaCreator (Just "aut") Nothing+ "Jonathan Lethem"+ ]+ , metaTitles = [MetaTitle Nothing+ "Ninety Percent of Everything"]+ }+ expected =+ ( "book"+ , "Kelly_Kessel_Lethem-NinetyPercentOfEverything.epub"+ )++ testNoAuthor :: Test testNoAuthor = TestCase $- assertNewName "no author(s) at all" meta expected+ assertNewName "no creator(s) at all" meta expected where meta = emptyMetadata+ { metaCreators = []+ , metaTitles = [MetaTitle Nothing+ "Some Collection of Fine Stories, Volume 1"]+ }+ expected =+ ( "book"+ , "SomeCollectionOfFineStoriesVolume1.epub"+ )+++testCreatorsNoAuthor :: Test+testCreatorsNoAuthor = TestCase $+ assertNewName "creators, but no author(s) at all" meta expected+ where+ meta = emptyMetadata { metaCreators = [ MetaCreator (Just "edt") Nothing "Graham Spindlewest"@@ -166,14 +228,14 @@ "Some Collection of Fine Stories, Volume 1"] } expected =- ( "SFBestOf"+ ( "book" , "SomeCollectionOfFineStoriesVolume1.epub" ) -testNoAuthorPubDate :: Test-testNoAuthorPubDate = TestCase $- assertNewName "no author(s) at all, with publication date" +testCreatorsNoAuthorPubDate :: Test+testCreatorsNoAuthorPubDate = TestCase $+ assertNewName "creators, but no author(s) at all, with pub date" meta expected where meta = emptyMetadata@@ -189,23 +251,23 @@ "2008"] } expected =- ( "SFBestOf"+ ( "book" , "SomeCollectionOfFineStoriesVolume1_2008.epub" ) -testAuthorDoubleAnd :: Test-testAuthorDoubleAnd = TestCase $- assertNewName "two authors separated by and" meta expected+testSeveralAuthors :: Test+testSeveralAuthors = TestCase $+ assertNewName "more than one author separated by & and/or and" meta expected where meta = emptyMetadata { metaCreators = [MetaCreator Nothing Nothing- "Kevin J. Anderson and Rebecca Moesta"]- , metaTitles = [MetaTitle Nothing "Rough Draft"]+ "Yvonne Q. Anderson & Eva Tunglewacker and Jefferson Milner"]+ , metaTitles = [MetaTitle Nothing "Big Trouble"] } expected =- ( "AuthorDouble"- , "Anderson_Moesta-RoughDraft.epub"+ ( "book"+ , "Anderson_Tunglewacker_Milner-BigTrouble.epub" ) @@ -218,7 +280,7 @@ , metaTitles = [MetaTitle Nothing "EON"] } expected =- ( "AuthorBasic"+ ( "book" , "BearGreg-Eon.epub" ) @@ -233,7 +295,7 @@ "Book 1: 3rd World Products, Inc."] } expected =- ( "AuthorBasic"+ ( "book" , "HowdersheltEd-Book1_3rdWorldProductsInc.epub" ) @@ -247,7 +309,7 @@ , metaTitles = [MetaTitle Nothing "SKitty [Shipscat series #1]"] } expected =- ( "AuthorBasic"+ ( "book" , "LackeyMercedes-Skitty_ShipscatSeries1.epub" ) @@ -277,7 +339,7 @@ "The *crazy*: Sand-box. Of Smedley's discontent, fear & Malnourishment? (Maybe not!); [Part #2]"] } expected =- ( "AuthorBasic"+ ( "book" , "MorelliDino-TheCrazy_SandBoxOfSmedleysDiscontentFearAndMalnourishmentMaybeNot_Part2.epub" ) @@ -292,7 +354,7 @@ , metaDates = [MetaDate (Just "original-publication") "2003"] } expected =- ( "AuthorBasic"+ ( "book" , "JonesJim-ATimelessStory_2003.epub" ) @@ -310,7 +372,7 @@ , metaDates = [MetaDate (Just "original-publication") "2003"] } expected =- ( "AuthorBasic"+ ( "book" , "JonesJim-ATimelessStory.epub" ) @@ -324,7 +386,7 @@ , metaTitles = [MetaTitle Nothing "Aeon Eight"] } expected =- ( "MagAeon"+ ( "magAeon" , "AeonMagazine08.epub" ) @@ -338,7 +400,7 @@ , metaTitles = [MetaTitle Nothing "Aeon Thirteen"] } expected =- ( "MagAeon"+ ( "magAeon" , "AeonMagazine13.epub" ) @@ -354,7 +416,7 @@ "Apex Science Fiction and Horror Digest #9"] } expected =- ( "MagApex"+ ( "magApex" , "ApexMagazine009.epub" ) @@ -370,14 +432,14 @@ "Apex Magazine Issue 17"] } expected =- ( "MagApex"+ ( "magApex" , "ApexMagazine017.epub" ) testChallengingDestinyShort :: Test testChallengingDestinyShort = TestCase $- assertNewName "Challenging Destiny Magazine, short" meta expected+ assertNewName "Challenging Destiny Magazine, short title" meta expected where meta = emptyMetadata { metaCreators = [MetaCreator Nothing Nothing@@ -386,14 +448,14 @@ "Challenging Destiny #23"] } expected =- ( "MagChallengingDestiny"+ ( "magChallengingDestiny" , "ChallengingDestinyMagazine023.epub" ) testChallengingDestinyLong :: Test testChallengingDestinyLong = TestCase $- assertNewName "Challenging Destiny Magazine, long" meta expected+ assertNewName "Challenging Destiny Magazine, long title" meta expected where meta = emptyMetadata { metaCreators = [MetaCreator Nothing Nothing @@ -402,28 +464,11 @@ "Challenging Destiny #24: August 2007"] } expected =- ( "MagChallengingDestiny"+ ( "magChallengingDestiny" , "ChallengingDestinyMagazine024.epub" ) -testChallengingDestinyPub :: Test-testChallengingDestinyPub = TestCase $- assertNewName "Challenging Destiny Magazine, Publishing in author"- meta expected- where- meta = emptyMetadata- { metaCreators = [MetaCreator Nothing Nothing - "Crystalline Sphere Publishing"]- , metaTitles = [MetaTitle Nothing - "Challenging Destiny #18"]- }- expected =- ( "MagChallengingDestiny"- , "ChallengingDestinyMagazine018.epub"- )-- testAnalog :: Test testAnalog = TestCase $ assertNewName "Analog" meta expected@@ -435,7 +480,7 @@ "Analog SFF, July-August 2003"] } expected =- ( "MagAnalog"+ ( "magAnalog" , "AnalogSF2003-07_08.epub" ) @@ -451,11 +496,33 @@ "Asimov's SF, August 2003"] } expected =- ( "MagAnalog"+ ( "magAnalog" , "AsimovsSF2003-08.epub" ) +testFantasyMagazine :: Test+testFantasyMagazine = TestCase $+ assertNewName "Fantasy Magazine" meta expected+ where+ meta = emptyMetadata+ { metaCreators =+ [ MetaCreator (Just "aut") (Just "Howard, Kat & Tanzer, Molly & Beagle, Peter S. & Howard, Jonathan L. & Valentine, Genevieve & Vaughn, Carrie & Pilinovsky, Helen") "Kat Howard"+ , MetaCreator (Just "aut") Nothing "Molly Tanzer"+ , MetaCreator (Just "aut") Nothing "Peter S. Beagle"+ , MetaCreator (Just "aut") Nothing "Jonathan L. Howard"+ , MetaCreator (Just "aut") Nothing "Genevieve Valentine"+ , MetaCreator (Just "aut") Nothing "Carrie Vaughn"+ , MetaCreator (Just "aut") Nothing "Helen Pilinovsky"+ ]+ , metaTitles = [MetaTitle Nothing+ "Fantasy Magazine Issue 49"]+ }+ expected =+ ( "magFantasyMag"+ , "FantasyMagazine049.epub"+ ) + testFsfShort :: Test testFsfShort = TestCase $ assertNewName "FSF Magazine, short" meta expected@@ -466,7 +533,7 @@ , metaTitles = [MetaTitle Nothing "FSF, April 2008"] } expected =- ( "MagFsf"+ ( "magFsf" , "FantasyScienceFiction2008-04.epub" ) @@ -482,11 +549,26 @@ "FSF Magazine, April 2006"] } expected =- ( "MagFsf"+ ( "magFsf" , "FantasyScienceFiction2006-04.epub" ) +testFsfAmpersand :: Test+testFsfAmpersand = TestCase $+ assertNewName "FSF Magazine, ampersand" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator Nothing Nothing+ "Spilogale"]+ , metaTitles = [MetaTitle Nothing "F & SF Dec 2003"]+ }+ expected =+ ( "magFsf"+ , "FantasyScienceFiction2003-12.epub"+ )++ testMagFutureOrbits :: Test testMagFutureOrbits = TestCase $ assertNewName "testMagFutureOrbits" meta expected@@ -498,7 +580,7 @@ "Future Orbits Issue 5, June/July 2002"] } expected =- ( "MagFutureOrbits"+ ( "magFutureOrbits" , "FutureOrbitsMagazine05_2002-06_07.epub" ) @@ -514,7 +596,7 @@ "GUD Magazine Issue 0 :: Spring 2007"] } expected =- ( "MagGud"+ ( "magGud" , "GUDMagazine00.epub" ) @@ -530,11 +612,27 @@ "GUD Magazine Issue 2 :: Spring 2008"] } expected =- ( "MagGud"+ ( "magGud" , "GUDMagazine02.epub" ) +testGudVeryLong :: Test+testGudVeryLong = TestCase $+ assertNewName "Gud Magazine, very long" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator Nothing Nothing + "GUD Magazine Authors"]+ , metaTitles = [MetaTitle Nothing + "Greatest Uncommon Denominator Magazine Issue 4 :: Spring 2009"]+ }+ expected =+ ( "magGud"+ , "GUDMagazine04.epub"+ )++ testInterzoneShort :: Test testInterzoneShort = TestCase $ assertNewName "Interzone Magazine, short" meta expected@@ -546,7 +644,7 @@ "Interzone SFF #212"] } expected =- ( "MagInterzone"+ ( "magInterzone" , "InterzoneSFF212.epub" ) @@ -562,7 +660,7 @@ "Interzone Science Fiction and Fantasy Magazine #216"] } expected =- ( "MagInterzone"+ ( "magInterzone" , "InterzoneSFF216.epub" ) @@ -578,7 +676,7 @@ "Nemesis Magazine #2"] } expected =- ( "MagNemesis"+ ( "magNemesis" , "NemesisMag002.epub" ) @@ -594,7 +692,7 @@ "Nemesis Magazine #7: Featuring Victory Rose in Death Stalks the Ruins"] } expected =- ( "MagNemesis"+ ( "magNemesis" , "NemesisMag007.epub" ) @@ -610,11 +708,28 @@ "Something Wicked SF and Horror Magazine #5"] } expected =- ( "MagSomethingWicked"- , "SomethingWickedMagazine05.epub"+ ( "magSomethingWicked"+ , "SomethingWicked005.epub" ) +testMagSomethingWickedMonth :: Test+testMagSomethingWickedMonth = TestCase $+ assertNewName "Something Wicked Magazine, month in title" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator (Just "aut")+ (Just "Authors, Something Wicked")+ "Something Wicked Authors"]+ , metaTitles = [MetaTitle Nothing + "Something Wicked #14 (October 2011)"]+ }+ expected =+ ( "magSomethingWicked"+ , "SomethingWicked014.epub"+ )++ testSFBestOf :: Test testSFBestOf = TestCase $ assertNewName "Science Fiction: The Best of the Year" meta expected@@ -626,11 +741,45 @@ "Science Fiction: The Best of the Year, 2007 Edition"] } expected =- ( "SFBestOf"+ ( "compOfTheYear" , "ScienceFiction_TheBestOfTheYear2007Edition.epub" ) +testBestSF :: Test+testBestSF = TestCase $+ assertNewName "The Best Science Fiction and Fantasy of the Year"+ meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator (Just "aut")+ (Just "Strahan, Jonathan")+ "Jonathan Strahan"]+ , metaTitles = [MetaTitle Nothing + "The Best Science Fiction and Fantasy of the Year: Volume 2"]+ }+ expected =+ ( "compOfTheYear"+ , "TheBestScienceFictionAndFantasyOfTheYear_Volume2.epub"+ )+++testYearsBest :: Test+testYearsBest = TestCase $+ assertNewName "The Year's Best SF" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator (Just "aut") Nothing + "Rich Horton, Michael Swanwick, Karen Joy Fowler"]+ , metaTitles = [MetaTitle Nothing + "The Year's Best Science Fiction: 2008 Edition"]+ }+ expected =+ ( "compYearsBest"+ , "TheYearsBestScienceFiction_2008Edition.epub"+ )++ testMagBlackStatic :: Test testMagBlackStatic = TestCase $ assertNewName "Black Static Magazine" meta expected@@ -642,7 +791,7 @@ "Black Static Horror Magazine #5"] } expected =- ( "MagNameIssue"+ ( "magBlackStatic" , "BlackStaticHorrorMagazine05.epub" ) @@ -658,7 +807,7 @@ "Rage Machine Magazine #1--December 2005"] } expected =- ( "MagRageMachine"+ ( "magRageMachine" , "RageMachineMagazine1_2005-12.epub" ) @@ -675,7 +824,7 @@ "Eclipse One"] } expected =- ( "MagEclipse"+ ( "magEclipse" , "Eclipse01.epub" ) @@ -697,7 +846,7 @@ "Beneath Ceaseless Skies #32"] } expected =- ( "MagBcs"+ ( "magBcs" , "BeneathCeaselessSkies_Issue032.epub" ) @@ -717,7 +866,7 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick_acme.epub" ) @@ -737,7 +886,7 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick.epub" ) @@ -755,7 +904,7 @@ , metaTitles = [MetaTitle Nothing "Moby Dick"] } expected =- ( "AuthorBasic"+ ( "book" , "MelvilleHerman-MobyDick.epub" ) @@ -773,7 +922,7 @@ , metaTitles = [MetaTitle Nothing "Jim Baen's Universe-Vol 4 Num 6"] } expected =- ( "MagUniverse"+ ( "magUniverse" , "JimBaensUniverseVol04Num06.epub" ) @@ -790,6 +939,57 @@ "Clarkesworld Magazine - Issue 21"] } expected =- ( "MagClarkesworld"+ ( "magClarkesworld" , "Clarkesworld021.epub"+ )+++testLightspeedDate :: Test+testLightspeedDate = TestCase $+ assertNewName "Lightspeed Magazine, date in title" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator (Just "aut") Nothing+ "Edited by John Joseph Adams"]+ , metaTitles = [MetaTitle Nothing + "Lightspeed Magazine, June 2010"]+ }+ expected =+ ( "magLightspeedDate"+ , "Lightspeed2010-06.epub"+ )+++testLightspeedIssue :: Test+testLightspeedIssue = TestCase $+ assertNewName "Lightspeed Magazine, issue number in title" meta expected+ where+ meta = emptyMetadata+ { metaCreators = [MetaCreator (Just "aut") (Just "Magazine, Lightspeed & Clark, Maggie & Valentine, Genevieve & Baxter, Stephen & Okorafor, Nnedi & Wilison, Daniel H. & Reed, Robert & Sedia, Ekaterina") "Lightspeed Magazine"]+ , metaTitles = [MetaTitle Nothing + "Lightspeed Magazine Issue 10"]+ }+ expected =+ ( "magLightspeedIssue"+ , "Lightspeed010.epub"+ )+++testMagWeirdTales :: Test+testMagWeirdTales = TestCase $+ assertNewName "Weird Tales magazine" meta expected+ where+ meta = emptyMetadata+ { metaCreators =+ [ MetaCreator (Just "aut") Nothing "VanderMeer"+ , MetaCreator (Just "aut") Nothing "Ann"+ , MetaCreator (Just "aut") Nothing "Spinrad"+ , MetaCreator (Just "aut") Nothing "Norman"+ ]+ , metaTitles = [MetaTitle Nothing + "Weird Tales #350"]+ }+ expected =+ ( "magWeirdTales"+ , "WeirdTales350.epub" )