diff options
-rw-r--r-- | compiler/src/Config.hs | 26 | ||||
-rw-r--r-- | compiler/src/Resource.hs | 43 | ||||
-rw-r--r-- | example/src/gallery.yaml | 4 | ||||
-rw-r--r-- | ldgallery.1.md | 27 |
4 files changed, 62 insertions, 38 deletions
diff --git a/compiler/src/Config.hs b/compiler/src/Config.hs index 4826f17..bf5a28e 100644 --- a/compiler/src/Config.hs +++ b/compiler/src/Config.hs | |||
@@ -19,17 +19,24 @@ | |||
19 | module Config | 19 | module Config |
20 | ( GalleryConfig(..) | 20 | ( GalleryConfig(..) |
21 | , CompilerConfig(..) | 21 | , CompilerConfig(..) |
22 | , TagsFromDirectoriesConfig(..) | ||
23 | , Resolution(..) | ||
22 | , readConfig | 24 | , readConfig |
23 | ) where | 25 | ) where |
24 | 26 | ||
25 | 27 | ||
26 | import GHC.Generics (Generic) | 28 | import GHC.Generics (Generic) |
27 | import Data.Aeson (FromJSON, withObject, (.:?), (.!=)) | 29 | import Data.Aeson (ToJSON, FromJSON, withObject, (.:?), (.!=)) |
28 | import qualified Data.Aeson as JSON | 30 | import qualified Data.Aeson as JSON |
29 | 31 | ||
30 | import Files (FileName) | 32 | import Files (FileName) |
31 | import Input (decodeYamlFile) | 33 | import Input (decodeYamlFile) |
32 | import Resource (Resolution(..)) | 34 | |
35 | |||
36 | data Resolution = Resolution | ||
37 | { width :: Int | ||
38 | , height :: Int | ||
39 | } deriving (Generic, Show, ToJSON, FromJSON) | ||
33 | 40 | ||
34 | 41 | ||
35 | data CompilerConfig = CompilerConfig | 42 | data CompilerConfig = CompilerConfig |
@@ -37,7 +44,7 @@ data CompilerConfig = CompilerConfig | |||
37 | , excludedDirectories :: [String] | 44 | , excludedDirectories :: [String] |
38 | , includedFiles :: [String] | 45 | , includedFiles :: [String] |
39 | , excludedFiles :: [String] | 46 | , excludedFiles :: [String] |
40 | , tagsFromDirectories :: Int | 47 | , tagsFromDirectories :: TagsFromDirectoriesConfig |
41 | , thumbnailMaxResolution :: Resolution | 48 | , thumbnailMaxResolution :: Resolution |
42 | , pictureMaxResolution :: Maybe Resolution | 49 | , pictureMaxResolution :: Maybe Resolution |
43 | } deriving (Generic, Show) | 50 | } deriving (Generic, Show) |
@@ -48,11 +55,22 @@ instance FromJSON CompilerConfig where | |||
48 | <*> v .:? "excludedDirectories" .!= [] | 55 | <*> v .:? "excludedDirectories" .!= [] |
49 | <*> v .:? "includedFiles" .!= ["*"] | 56 | <*> v .:? "includedFiles" .!= ["*"] |
50 | <*> v .:? "excludedFiles" .!= [] | 57 | <*> v .:? "excludedFiles" .!= [] |
51 | <*> v .:? "tagsFromDirectories" .!= 0 | 58 | <*> v .:? "tagsFromDirectories" .!= (TagsFromDirectoriesConfig 0 "") |
52 | <*> v .:? "thumbnailMaxResolution" .!= (Resolution 400 300) | 59 | <*> v .:? "thumbnailMaxResolution" .!= (Resolution 400 300) |
53 | <*> v .:? "pictureMaxResolution" | 60 | <*> v .:? "pictureMaxResolution" |
54 | 61 | ||
55 | 62 | ||
63 | data TagsFromDirectoriesConfig = TagsFromDirectoriesConfig | ||
64 | { fromParents :: Int | ||
65 | , prefix :: String | ||
66 | } deriving (Generic, Show) | ||
67 | |||
68 | instance FromJSON TagsFromDirectoriesConfig where | ||
69 | parseJSON = withObject "TagsFromDirectoriesConfig" $ \v -> TagsFromDirectoriesConfig | ||
70 | <$> v .:? "fromParents" .!= 0 | ||
71 | <*> v .:? "prefix" .!= "" | ||
72 | |||
73 | |||
56 | data GalleryConfig = GalleryConfig | 74 | data GalleryConfig = GalleryConfig |
57 | { compiler :: CompilerConfig | 75 | { compiler :: CompilerConfig |
58 | , viewer :: JSON.Object | 76 | , viewer :: JSON.Object |
diff --git a/compiler/src/Resource.hs b/compiler/src/Resource.hs index aadf60b..b2a6bbf 100644 --- a/compiler/src/Resource.hs +++ b/compiler/src/Resource.hs | |||
@@ -27,7 +27,7 @@ import Control.Concurrent.ParallelIO.Global (parallel) | |||
27 | import Data.List (sortOn) | 27 | import Data.List (sortOn) |
28 | import Data.List.Ordered (minusBy) | 28 | import Data.List.Ordered (minusBy) |
29 | import Data.Char (toLower) | 29 | import Data.Char (toLower) |
30 | import Data.Maybe (mapMaybe, fromMaybe, maybeToList) | 30 | import Data.Maybe (mapMaybe, fromMaybe) |
31 | import Data.Function ((&)) | 31 | import Data.Function ((&)) |
32 | import qualified Data.Set as Set | 32 | import qualified Data.Set as Set |
33 | import Data.Text (pack) | 33 | import Data.Text (pack) |
@@ -37,10 +37,11 @@ import Data.Time.Format (formatTime, defaultTimeLocale) | |||
37 | import Safe.Foldable (maximumByMay) | 37 | import Safe.Foldable (maximumByMay) |
38 | 38 | ||
39 | import GHC.Generics (Generic) | 39 | import GHC.Generics (Generic) |
40 | import Data.Aeson (FromJSON, ToJSON, genericToJSON, genericToEncoding) | 40 | import Data.Aeson (ToJSON, genericToJSON, genericToEncoding) |
41 | import qualified Data.Aeson as JSON | 41 | import qualified Data.Aeson as JSON |
42 | 42 | ||
43 | import Files | 43 | import Files |
44 | import Config (Resolution(..), TagsFromDirectoriesConfig(..)) | ||
44 | import Input (InputTree(..), Sidecar(..)) | 45 | import Input (InputTree(..), Sidecar(..)) |
45 | 46 | ||
46 | 47 | ||
@@ -57,16 +58,6 @@ encodingOptions = JSON.defaultOptions | |||
57 | 58 | ||
58 | type Tag = String | 59 | type Tag = String |
59 | 60 | ||
60 | data Resolution = Resolution | ||
61 | { width :: Int | ||
62 | , height :: Int | ||
63 | } deriving (Generic, Show, FromJSON) | ||
64 | |||
65 | instance ToJSON Resolution where | ||
66 | toJSON = genericToJSON encodingOptions | ||
67 | toEncoding = genericToEncoding encodingOptions | ||
68 | |||
69 | |||
70 | data Resource = Resource | 61 | data Resource = Resource |
71 | { resourcePath :: Path | 62 | { resourcePath :: Path |
72 | , modTime :: UTCTime | 63 | , modTime :: UTCTime |
@@ -120,13 +111,13 @@ type ThumbnailProcessor = Path -> IO (Maybe Thumbnail) | |||
120 | 111 | ||
121 | 112 | ||
122 | buildGalleryTree :: | 113 | buildGalleryTree :: |
123 | ItemProcessor -> ThumbnailProcessor | 114 | ItemProcessor -> ThumbnailProcessor -> TagsFromDirectoriesConfig |
124 | -> Int -> InputTree -> IO GalleryItem | 115 | -> InputTree -> IO GalleryItem |
125 | buildGalleryTree processItem processThumbnail tagsFromDirectories inputTree = | 116 | buildGalleryTree processItem processThumbnail tagsFromDirsConfig inputTree = |
126 | mkGalleryItem [] [] inputTree | 117 | mkGalleryItem [] inputTree |
127 | where | 118 | where |
128 | mkGalleryItem :: [String] -> [Tag] -> InputTree -> IO GalleryItem | 119 | mkGalleryItem :: [Tag] -> InputTree -> IO GalleryItem |
129 | mkGalleryItem parentDirs inheritedTags InputFile{path, modTime, sidecar} = | 120 | mkGalleryItem inheritedTags InputFile{path, modTime, sidecar} = |
130 | do | 121 | do |
131 | properties <- processItem path | 122 | properties <- processItem path |
132 | processedThumbnail <- processThumbnail path | 123 | processedThumbnail <- processThumbnail path |
@@ -134,23 +125,22 @@ buildGalleryTree processItem processThumbnail tagsFromDirectories inputTree = | |||
134 | { title = Input.title sidecar ?? fileName path ?? "" | 125 | { title = Input.title sidecar ?? fileName path ?? "" |
135 | , datetime = Input.datetime sidecar ?? toZonedTime modTime | 126 | , datetime = Input.datetime sidecar ?? toZonedTime modTime |
136 | , description = Input.description sidecar ?? "" | 127 | , description = Input.description sidecar ?? "" |
137 | , tags = unique ((Input.tags sidecar ?? []) ++ inheritedTags ++ parentDirTags parentDirs) | 128 | , tags = unique ((Input.tags sidecar ?? []) ++ inheritedTags ++ parentDirTags path) |
138 | , path = "/" /> path | 129 | , path = "/" /> path |
139 | , thumbnail = processedThumbnail | 130 | , thumbnail = processedThumbnail |
140 | , properties = properties } | 131 | , properties = properties } |
141 | 132 | ||
142 | mkGalleryItem parentDirs inheritedTags InputDir{path, modTime, sidecar, dirThumbnailPath, items} = | 133 | mkGalleryItem inheritedTags InputDir{path, modTime, sidecar, dirThumbnailPath, items} = |
143 | do | 134 | do |
144 | let itemsParents = (maybeToList $ fileName path) ++ parentDirs | ||
145 | let dirTags = (Input.tags sidecar ?? []) ++ inheritedTags | 135 | let dirTags = (Input.tags sidecar ?? []) ++ inheritedTags |
146 | processedItems <- parallel $ map (mkGalleryItem itemsParents dirTags) items | 136 | processedItems <- parallel $ map (mkGalleryItem dirTags) items |
147 | processedThumbnail <- maybeThumbnail dirThumbnailPath | 137 | processedThumbnail <- maybeThumbnail dirThumbnailPath |
148 | return GalleryItem | 138 | return GalleryItem |
149 | { title = Input.title sidecar ?? fileName path ?? "" | 139 | { title = Input.title sidecar ?? fileName path ?? "" |
150 | , datetime = Input.datetime sidecar ?? mostRecentModTime processedItems | 140 | , datetime = Input.datetime sidecar ?? mostRecentModTime processedItems |
151 | ?? toZonedTime modTime | 141 | ?? toZonedTime modTime |
152 | , description = Input.description sidecar ?? "" | 142 | , description = Input.description sidecar ?? "" |
153 | , tags = unique (aggregateTags processedItems ++ parentDirTags parentDirs) | 143 | , tags = unique (aggregateTags processedItems ++ parentDirTags path) |
154 | , path = "/" /> path | 144 | , path = "/" /> path |
155 | , thumbnail = processedThumbnail | 145 | , thumbnail = processedThumbnail |
156 | , properties = Directory processedItems } | 146 | , properties = Directory processedItems } |
@@ -162,8 +152,11 @@ buildGalleryTree processItem processThumbnail tagsFromDirectories inputTree = | |||
162 | unique :: Ord a => [a] -> [a] | 152 | unique :: Ord a => [a] -> [a] |
163 | unique = Set.toList . Set.fromList | 153 | unique = Set.toList . Set.fromList |
164 | 154 | ||
165 | parentDirTags :: [String] -> [Tag] | 155 | parentDirTags :: Path -> [Tag] |
166 | parentDirTags = take tagsFromDirectories | 156 | parentDirTags (Path elements) = |
157 | drop 1 elements | ||
158 | & take (fromParents tagsFromDirsConfig) | ||
159 | & map (prefix tagsFromDirsConfig ++) | ||
167 | 160 | ||
168 | aggregateTags :: [GalleryItem] -> [Tag] | 161 | aggregateTags :: [GalleryItem] -> [Tag] |
169 | aggregateTags = concatMap (\item -> tags (item::GalleryItem)) | 162 | aggregateTags = concatMap (\item -> tags (item::GalleryItem)) |
diff --git a/example/src/gallery.yaml b/example/src/gallery.yaml index bef19e0..3408571 100644 --- a/example/src/gallery.yaml +++ b/example/src/gallery.yaml | |||
@@ -8,7 +8,9 @@ compiler: | |||
8 | #excludedFiles: | 8 | #excludedFiles: |
9 | #- "*.md" | 9 | #- "*.md" |
10 | 10 | ||
11 | tagsFromDirectories: 0 # default | 11 | tagsFromDirectories: |
12 | fromParents: 0 # default | ||
13 | prefix: "" # default | ||
12 | 14 | ||
13 | thumbnailMaxResolution: | 15 | thumbnailMaxResolution: |
14 | width: 400 # default | 16 | width: 400 # default |
diff --git a/ldgallery.1.md b/ldgallery.1.md index 91724a6..a5d0e4c 100644 --- a/ldgallery.1.md +++ b/ldgallery.1.md | |||
@@ -107,19 +107,28 @@ tags | |||
107 | The gallery settings reside in a file named "gallery.yaml" located at the root of the gallery's source directory. | 107 | The gallery settings reside in a file named "gallery.yaml" located at the root of the gallery's source directory. |
108 | 108 | ||
109 | compiler.includedDirectories[] | 109 | compiler.includedDirectories[] |
110 | : Glob patterns of directory names to include in the gallery. Defaults to ["*"] (matches all directory names). | 110 | : Glob patterns of directory names to include in the gallery. |
111 | Defaults to ["*"] (matches all directory names). | ||
111 | 112 | ||
112 | compiler.excludedDirectories[] | 113 | compiler.excludedDirectories[] |
113 | : Glob patterns of directory names to exclude from the gallery. Defaults to [] (none). | 114 | : Glob patterns of directory names to exclude from the gallery. |
115 | Defaults to [] (none). | ||
114 | 116 | ||
115 | compiler.includedFiles[] | 117 | compiler.includedFiles[] |
116 | : Glob patterns of file names to include in the gallery. Defaults to ["*"] (matches all file names). | 118 | : Glob patterns of file names to include in the gallery. |
119 | Defaults to ["*"] (matches all file names). | ||
117 | 120 | ||
118 | compiler.excludedFiles[] | 121 | compiler.excludedFiles[] |
119 | : Glob patterns of file names to exclude from the gallery. Defaults to [] (none). | 122 | : Glob patterns of file names to exclude from the gallery. |
123 | Defaults to [] (none). | ||
120 |