diff options
-rw-r--r-- | compiler/app/Main.hs | 21 | ||||
-rw-r--r-- | compiler/src/Compiler.hs | 59 | ||||
-rw-r--r-- | example/.gitignore | 3 | ||||
-rw-r--r-- | example/gallery.yaml | 6 | ||||
-rw-r--r-- | example/index.json | 111 |
5 files changed, 56 insertions, 144 deletions
diff --git a/compiler/app/Main.hs b/compiler/app/Main.hs index be57c82..d9b019a 100644 --- a/compiler/app/Main.hs +++ b/compiler/app/Main.hs | |||
@@ -29,29 +29,38 @@ import Compiler | |||
29 | 29 | ||
30 | data Args = Args | 30 | data Args = Args |
31 | { inputDir :: String | 31 | { inputDir :: String |
32 | , outputDir :: String } | 32 | , outputDir :: String |
33 | , rebuild :: Bool } | ||
33 | 34 | ||
34 | args :: Parser Args | 35 | args :: Parser Args |
35 | args = Args | 36 | args = Args |
36 | <$> strOption | 37 | <$> strOption |
37 | ( long "input" | 38 | ( long "input" |
38 | <> short 'i' | 39 | <> short 'i' |
39 | <> metavar "INPUT DIR" | 40 | <> metavar "SOURCE DIR" |
41 | <> value "./" | ||
42 | <> showDefault | ||
40 | <> help "Gallery source directory" ) | 43 | <> help "Gallery source directory" ) |
41 | <*> strOption | 44 | <*> strOption |
42 | ( long "output" | 45 | ( long "output" |
43 | <> short 'o' | 46 | <> short 'o' |
44 | <> metavar "OUTPUT DIR" | 47 | <> metavar "OUTPUT DIR" |
45 | <> help "Generated gallery output path, outside of the input directory" ) | 48 | <> value "./out" |
49 | <> showDefault | ||
50 | <> help "Generated gallery output path" ) | ||
51 | <*> switch | ||
52 | ( long "rebuild" | ||
53 | <> short 'r' | ||
54 | <> help "Invalidate cache and recompile everything" ) | ||
46 | 55 | ||
47 | main :: IO () | 56 | main :: IO () |
48 | main = | 57 | main = |
49 | do | 58 | do |
50 | options <- execParser opts | 59 | options <- execParser opts |
51 | compileGallery (inputDir options) (outputDir options) | 60 | compileGallery (inputDir options) (outputDir options) (rebuild options) |
52 | 61 | ||
53 | where | 62 | where |
54 | opts = info (args <**> helper) | 63 | opts = info (args <**> helper) |
55 | ( fullDesc | 64 | ( fullDesc |
56 | <> progDesc "Compile a picture gallery" | 65 | <> progDesc "Compile a gallery" |
57 | <> header "ldgallery - A static generator which turns a collection of tagged pictures into a searchable web gallery.") | 66 | <> header "ldgallery - a static gallery generator with tags" ) |
diff --git a/compiler/src/Compiler.hs b/compiler/src/Compiler.hs index 854fd03..2584570 100644 --- a/compiler/src/Compiler.hs +++ b/compiler/src/Compiler.hs | |||
@@ -27,31 +27,33 @@ module Compiler | |||
27 | ) where | 27 | ) where |
28 | 28 | ||
29 | 29 | ||
30 | import Control.Monad | 30 | import Control.Monad (liftM2) |
31 | import Data.Function ((&)) | 31 | import Data.Function ((&)) |
32 | import Data.List (any) | ||
32 | import System.FilePath ((</>)) | 33 | import System.FilePath ((</>)) |
33 | 34 | ||
34 | import Data.Aeson (ToJSON) | 35 | import Data.Aeson (ToJSON) |
35 | import qualified Data.Aeson as JSON | 36 | import qualified Data.Aeson as JSON |
36 | 37 | ||
37 | import Config | 38 | import Config |
39 | import Input (decodeYamlFile, readInputTree) | ||
40 | import Resource (ResourceTree, buildResourceTree, cleanupResourceDir) | ||
41 | import Gallery (buildGalleryTree) | ||
38 | import Files | 42 | import Files |
39 | ( FileName | 43 | ( FileName |
44 | , FSNode(..) | ||
40 | , readDirectory | 45 | , readDirectory |
41 | , localPath | ||
42 | , isHidden | 46 | , isHidden |
43 | , nodeName | 47 | , nodeName |
44 | , filterDir | 48 | , filterDir |
45 | , flattenDir | ||
46 | , root | ||
47 | , (/>) | ||
48 | , ensureParentDir | 49 | , ensureParentDir |
49 | , isOutdated ) | 50 | , isOutdated ) |
50 | |||
51 | import Input (decodeYamlFile, readInputTree) | ||
52 | import Resource (ResourceTree, buildResourceTree, cleanupResourceDir) | ||
53 | import Gallery (buildGalleryTree) | ||
54 | import Processors | 51 | import Processors |
52 | ( dirFileProcessor | ||
53 | , itemFileProcessor | ||
54 | , thumbnailFileProcessor | ||
55 | , skipCached | ||
56 | , withCached ) | ||
55 | 57 | ||
56 | 58 | ||
57 | writeJSON :: ToJSON a => FileName -> a -> IO () | 59 | writeJSON :: ToJSON a => FileName -> a -> IO () |
@@ -61,26 +63,21 @@ writeJSON outputPath object = | |||
61 | ensureParentDir JSON.encodeFile outputPath object | 63 | ensureParentDir JSON.encodeFile outputPath object |
62 | 64 | ||
63 | 65 | ||
64 | compileGallery :: FilePath -> FilePath -> IO () | 66 | compileGallery :: FilePath -> FilePath -> Bool -> IO () |
65 | compileGallery inputDirPath outputDirPath = | 67 | compileGallery inputDirPath outputDirPath rebuildAll = |
66 | do | 68 | do |
67 | fullConfig <- readConfig inputGalleryConf | 69 | fullConfig <- readConfig inputGalleryConf |
68 | let config = compiler fullConfig | 70 | let config = compiler fullConfig |
69 | 71 | ||
70 | -- TODO: exclude output dir if it's under the input dir | ||
71 | inputDir <- readDirectory inputDirPath | 72 | inputDir <- readDirectory inputDirPath |
72 | 73 | let sourceTree = filterDir galleryDirFilter inputDir | |
73 | let isGalleryFile = \n -> nodeName n == galleryConf | 74 | inputTree <- readInputTree sourceTree |
74 | let galleryTree = filterDir (liftM2 (&&) (not . isGalleryFile) (not . isHidden)) inputDir | ||
75 | |||
76 | inputTree <- readInputTree galleryTree | ||
77 | 75 | ||
78 | invalidateCache <- isOutdated inputGalleryConf outputIndex | 76 | invalidateCache <- isOutdated inputGalleryConf outputIndex |
79 | let cache = if invalidateCache then skipCached else withCached | 77 | let cache = if invalidateCache || rebuildAll then skipCached else withCached |
80 | let dirProc = dirFileProcessor inputDirPath outputDirPath itemsDir | 78 | let itemProc = itemProcessor (pictureMaxResolution config) cache |
81 | let itemProc = itemFileProcessor (pictureMaxResolution config) cache inputDirPath outputDirPath itemsDir | 79 | let thumbnailProc = thumbnailProcessor (thumbnailResolution config) cache |
82 | let thumbnailProc = thumbnailFileProcessor (thumbnailResolution config) cache inputDirPath outputDirPath thumbnailsDir | 80 | resourceTree <- buildResourceTree dirProcessor itemProc thumbnailProc inputTree |
83 | resourceTree <- buildResourceTree dirProc itemProc thumbnailProc inputTree | ||
84 | 81 | ||
85 | cleanupResourceDir resourceTree outputDirPath | 82 | cleanupResourceDir resourceTree outputDirPath |
86 | 83 | ||
@@ -92,9 +89,23 @@ compileGallery inputDirPath outputDirPath = | |||
92 | 89 | ||
93 | where | 90 | where |
94 | galleryConf = "gallery.yaml" | 91 | galleryConf = "gallery.yaml" |
92 | indexFile = "index.json" | ||
93 | viewerConfFile = "viewer.json" | ||
95 | itemsDir = "items" | 94 | itemsDir = "items" |
96 | thumbnailsDir = "thumbnails" | 95 | thumbnailsDir = "thumbnails" |
97 | 96 | ||
98 | inputGalleryConf = inputDirPath </> galleryConf | 97 | inputGalleryConf = inputDirPath </> galleryConf |
99 | outputIndex = outputDirPath </> "index.json" | 98 | outputIndex = outputDirPath </> indexFile |
100 | outputViewerConf = outputDirPath </> "viewer.json" | 99 | outputViewerConf = outputDirPath </> viewerConfFile |
100 | |||
101 | (&&&) = liftM2 (&&) | ||
102 | galleryDirFilter = (not . containsOutputGallery) &&& (not . isConfigFile) &&& (not . isHidden) | ||
103 | isConfigFile = (==) galleryConf . nodeName | ||
104 | containsOutputGallery (File _) = False | ||
105 | containsOutputGallery (Dir _ items) = any ((==) indexFile . nodeName) items | ||
106 | |||
107 | dirProcessor = dirFileProcessor inputDirPath outputDirPath itemsDir | ||
108 | itemProcessor maxRes cache = | ||
109 | itemFileProcessor maxRes cache inputDirPath outputDirPath itemsDir | ||
110 | thumbnailProcessor thumbRes cache = | ||
111 | thumbnailFileProcessor thumbRes cache inputDirPath outputDirPath thumbnailsDir | ||
diff --git a/example/.gitignore b/example/.gitignore index f1212bc..1fcb152 100644 --- a/example/.gitignore +++ b/example/.gitignore | |||
@@ -1,2 +1 @@ | |||
1 | items | out | |
2 | thumbnails | ||
diff --git a/example/gallery.yaml b/example/gallery.yaml index fc4bdf9..0a16e59 100644 --- a/example/gallery.yaml +++ b/example/gallery.yaml | |||
@@ -1,2 +1,6 @@ | |||
1 | compiler: {} | 1 | compiler: |
2 | pictureMaxResolution: | ||
3 | width: 1024 | ||
4 | height: 768 | ||
5 | |||
2 | viewer: {} | 6 | viewer: {} |
diff --git a/example/index.json b/example/index.json deleted file mode 100644 index d693f7b..0000000 --- a/example/index.json +++ /dev/null | |||
@@ -1,111 +0,0 @@ | |||
1 | { | ||
2 | "_comment": "reference gallery index file, manually aggregated", | ||
3 | |||
4 | "title": "", | ||
5 | "date": "", | ||
6 | "description": "", | ||
7 | "tags": [ | ||
8 | "photographer.nphilou", | ||
9 | "location.germany.berlin", | ||
10 | "books", | ||
11 | "book-shop", | ||
12 | "location.switzerland.ormont-dessus", | ||
13 | "glacier3000", | ||
14 | "time.day", | ||
15 | "weather.foggy", | ||
16 | "forest", | ||
17 | "trees", | ||
18 | "catwalk", | ||
19 | "mountain" | ||
20 | ], | ||
21 | "path": "/", | ||
22 | "thumbnail": null, | ||
23 | "properties": { | ||
24 | "type": "directory", | ||
25 | "items": [ | ||
26 | { | ||
27 | "title": "Book shop", | ||
28 | "date": "2016:12:19T16:48:50+02:00", | ||
29 | "description": "© Philippe NGUYEN", | ||
30 | "tags": [ | ||
31 | "photographer.nphilou", | ||
32 | "location.germany.berlin", | ||
33 | "books", | ||
34 | "book-shop" | ||
35 | ], | ||
36 | "path": "/items/_DSC8808-1.jpg", | ||
37 | "thumbnail": "/thumbnails/_DSC8808-1.jpg", | ||
38 | "properties": { | ||
39 | "type": "image", | ||
40 | "filesize": 987, | ||
41 | "resolution": { "width": 3840, "height": 2160 } | ||
42 | } | ||
43 | }, | ||
44 | { | ||
45 | "title": "Glacier 3000", | ||
46 | "date": "", | ||
47 | "description": "", | ||
48 | "tags": [ | ||
49 | "photographer.nphilou", | ||
50 | "location.switzerland.ormont-dessus", | ||
51 | "glacier3000", | ||
52 | "time.day", | ||
53 | "weather.foggy", | ||
54 | "forest", | ||
55 | "trees", | ||
56 | "c |