diff options
author | pacien | 2020-02-26 22:13:00 +0100 |
---|---|---|
committer | Notkea | 2020-02-27 21:54:32 +0100 |
commit | f09e9d9fa29284bd9ae872efe5ba1d526e349011 (patch) | |
tree | 50d523ffb4f2d6e4b1d09eb2edd9f099c9b20048 | |
parent | c7fa5bd40d0e5c9ea50190a90a0ccfee8ad96c25 (diff) | |
download | ldgallery-f09e9d9fa29284bd9ae872efe5ba1d526e349011.tar.gz |
compiler: add tag inclusion and exclusion globs
GitHub: closes #30
-rw-r--r-- | compiler/ldgallery.1.md | 11 | ||||
-rw-r--r-- | compiler/src/Compiler.hs | 30 | ||||
-rw-r--r-- | compiler/src/Config.hs | 4 | ||||
-rw-r--r-- | compiler/src/Input.hs | 13 | ||||
-rw-r--r-- | example/src/gallery.yaml | 15 |
5 files changed, 57 insertions, 16 deletions
diff --git a/compiler/ldgallery.1.md b/compiler/ldgallery.1.md index 59a5b30..3c52f9d 100644 --- a/compiler/ldgallery.1.md +++ b/compiler/ldgallery.1.md | |||
@@ -130,10 +130,19 @@ includedFiles[] | |||
130 | excludedFiles[] | 130 | excludedFiles[] |
131 | : Glob patterns of file names to exclude from the gallery. Defaults to [] (none). | 131 | : Glob patterns of file names to exclude from the gallery. Defaults to [] (none). |
132 | 132 | ||
133 | includedTags[] | ||
134 | : Glob patterns of tags to include in the gallery. | ||
135 | Items with no tags can be matched with the empty pattern. | ||
136 | Defaults to ["*"] (matches all tags, includes untagged items). | ||
137 | |||
138 | excludedTags[] | ||
139 | : Glob patterns of tags to exclude from the gallery. | ||
140 | Defaults to [] (none). | ||
141 | |||
133 | tagsFromDirectories.fromParents | 142 | tagsFromDirectories.fromParents |
134 | : Automatically generate tags from the name of parent directories, | 143 | : Automatically generate tags from the name of parent directories, |
135 | looking up in the hierarchy as far as indicated by this parameter. | 144 | looking up in the hierarchy as far as indicated by this parameter. |
136 | Defaults to 0 (do not generate tags from parent directories). | 145 | Defaults to 0 (does not generate tags from parent directories). |
137 | 146 | ||
138 | tagsFromDirectories.prefix | 147 | tagsFromDirectories.prefix |
139 | : Prefix to use for tags automatically generated from the parent directories' names. | 148 | : Prefix to use for tags automatically generated from the parent directories' names. |
diff --git a/compiler/src/Compiler.hs b/compiler/src/Compiler.hs index 51f5065..fa405a2 100644 --- a/compiler/src/Compiler.hs +++ b/compiler/src/Compiler.hs | |||
@@ -25,6 +25,7 @@ module Compiler | |||
25 | import GHC.Generics (Generic) | 25 | import GHC.Generics (Generic) |
26 | import Control.Monad (liftM2, when) | 26 | import Control.Monad (liftM2, when) |
27 | import Data.List (any) | 27 | import Data.List (any) |
28 | import Data.Maybe (fromMaybe) | ||
28 | import System.FilePath ((</>)) | 29 | import System.FilePath ((</>)) |
29 | import qualified System.FilePath.Glob as Glob | 30 | import qualified System.FilePath.Glob as Glob |
30 | import System.Directory (canonicalizePath) | 31 | import System.Directory (canonicalizePath) |
@@ -33,7 +34,7 @@ import Data.Aeson (ToJSON) | |||
33 | import qualified Data.Aeson as JSON | 34 | import qualified Data.Aeson as JSON |
34 | 35 | ||
35 | import Config | 36 | import Config |
36 | import Input (readInputTree) | 37 | import Input (InputTree, readInputTree, filterInputTree, sidecar, tags) |
37 | import Resource (GalleryItem, buildGalleryTree, galleryCleanupResourceDir) | 38 | import Resource (GalleryItem, buildGalleryTree, galleryCleanupResourceDir) |
38 | import Files | 39 | import Files |
39 | ( FileName | 40 | ( FileName |
@@ -74,6 +75,15 @@ writeJSON outputPath object = | |||
74 | ensureParentDir JSON.encodeFile outputPath object | 75 | ensureParentDir JSON.encodeFile outputPath object |
75 | 76 | ||
76 | 77 | ||
78 | (&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool | ||
79 | (&&&) = liftM2 (&&) | ||
80 | |||
81 | (|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool | ||
82 | (|||) = liftM2 (||) | ||
83 | |||
84 | anyPattern :: [String] -> String -> Bool | ||
85 | anyPattern patterns string = any (flip Glob.match string) (map Glob.compile patterns) | ||
86 | |||
77 | galleryDirFilter :: GalleryConfig -> [FilePath] -> FSNode -> Bool | 87 | galleryDirFilter :: GalleryConfig -> [FilePath] -> FSNode -> Bool |
78 | galleryDirFilter config excludedCanonicalDirs = | 88 | galleryDirFilter config excludedCanonicalDirs = |
79 | (not . isHidden) | 89 | (not . isHidden) |
@@ -84,9 +94,6 @@ galleryDirFilter config excludedCanonicalDirs = | |||
84 | (matchesFile $ anyPattern $ excludedFiles config))) | 94 | (matchesFile $ anyPattern $ excludedFiles config))) |
85 | 95 | ||
86 | where | 96 | where |
87 | (&&&) = liftM2 (&&) | ||
88 | (|||) = liftM2 (||) | ||
89 | |||
90 | matchesDir :: (FileName -> Bool) -> FSNode -> Bool | 97 | matchesDir :: (FileName -> Bool) -> FSNode -> Bool |
91 | matchesDir cond dir@Dir{} = maybe False cond $ nodeName dir | 98 | matchesDir cond dir@Dir{} = maybe False cond $ nodeName dir |
92 | matchesDir _ File{} = False | 99 | matchesDir _ File{} = False |
@@ -95,13 +102,19 @@ galleryDirFilter config excludedCanonicalDirs = | |||
95 | matchesFile cond file@File{} = maybe False cond $ nodeName file | 102 | matchesFile cond file@File{} = maybe False cond $ nodeName file |
96 | matchesFile _ Dir{} = False | 103 | matchesFile _ Dir{} = False |
97 | 104 | ||
98 | anyPattern :: [String] -> FileName -> Bool | ||
99 | anyPattern patterns filename = any (flip Glob.match filename) (map Glob.compile patterns) | ||
100 | |||
101 | isExcludedDir :: FSNode -> Bool | 105 | isExcludedDir :: FSNode -> Bool |
102 | isExcludedDir Dir{canonicalPath} = any (canonicalPath ==) excludedCanonicalDirs | 106 | isExcludedDir Dir{canonicalPath} = any (canonicalPath ==) excludedCanonicalDirs |
103 | isExcludedDir File{} = False | 107 | isExcludedDir File{} = False |
104 | 108 | ||
109 | inputTreeFilter :: GalleryConfig -> InputTree -> Bool | ||
110 | inputTreeFilter GalleryConfig{includedTags, excludedTags} = | ||
111 | (hasTagMatching $ anyPattern includedTags) | ||
112 | &&& (not . (hasTagMatching $ anyPattern excludedTags)) | ||
113 | |||
114 | where | ||
115 | hasTagMatching :: (String -> Bool) -> InputTree -> Bool | ||
116 | hasTagMatching cond = (any cond) . (fromMaybe [""] . tags) . sidecar | ||
117 | |||
105 | 118 | ||
106 | compileGallery :: FilePath -> FilePath -> FilePath -> FilePath -> [FilePath] -> Bool -> Bool -> IO () | 119 | compileGallery :: FilePath -> FilePath -> FilePath -> FilePath -> [FilePath] -> Bool -> Bool -> IO () |
107 | compileGallery configPath inputDirPath outputDirPath outputIndexPath excludedDirs rebuildAll cleanOutput = | 120 | compileGallery configPath inputDirPath outputDirPath outputIndexPath excludedDirs rebuildAll cleanOutput = |
@@ -113,12 +126,13 @@ compileGallery configPath inputDirPath outputDirPath outputIndexPath excludedDir | |||
113 | let sourceFilter = galleryDirFilter config excludedCanonicalDirs | 126 | let sourceFilter = galleryDirFilter config excludedCanonicalDirs |
114 | let sourceTree = filterDir sourceFilter inputDir | 127 | let sourceTree = filterDir sourceFilter inputDir |
115 | inputTree <- readInputTree sourceTree | 128 | inputTree <- readInputTree sourceTree |
129 | let curatedInputTree = filterInputTree (inputTreeFilter config) inputTree | ||
116 | 130 | ||
117 | let cache = if rebuildAll then skipCached else withCached | 131 | let cache = if rebuildAll then skipCached else withCached |
118 | let itemProc = itemProcessor config cache | 132 | let itemProc = itemProcessor config cache |
119 | let thumbnailProc = thumbnailProcessor config cache | 133 | let thumbnailProc = thumbnailProcessor config cache |
120 | let galleryBuilder = buildGalleryTree itemProc thumbnailProc (tagsFromDirectories config) | 134 | let galleryBuilder = buildGalleryTree itemProc thumbnailProc (tagsFromDirectories config) |
121 | resources <- galleryBuilder inputTree | 135 | resources <- galleryBuilder curatedInputTree |
122 | 136 | ||
123 | when cleanOutput $ galleryCleanupResourceDir resources outputDirPath | 137 | when cleanOutput $ galleryCleanupResourceDir resources outputDirPath |
124 | writeJSON (outputGalleryIndex outputIndexPath) $ GalleryIndex (viewerConfig config) resources | 138 | writeJSON (outputGalleryIndex outputIndexPath) $ GalleryIndex (viewerConfig config) resources |
diff --git a/compiler/src/Config.hs b/compiler/src/Config.hs index 1bdb2b8..8796c3c 100644 --- a/compiler/src/Config.hs +++ b/compiler/src/Config.hs | |||
@@ -55,6 +55,8 @@ data GalleryConfig = GalleryConfig | |||
55 | , excludedDirectories :: [String] | 55 | , excludedDirectories :: [String] |
56 | , includedFiles :: [String] | 56 | , includedFiles :: [String] |
57 | , excludedFiles :: [String] | 57 | , excludedFiles :: [String] |
58 | , includedTags :: [String] | ||
59 | , excludedTags :: [String] | ||
58 | , tagsFromDirectories :: TagsFromDirectoriesConfig | 60 | , tagsFromDirectories :: TagsFromDirectoriesConfig |
59 | , thumbnailMaxResolution :: Resolution | 61 | , thumbnailMaxResolution :: Resolution |
60 | , pictureMaxResolution :: Maybe Resolution | 62 | , pictureMaxResolution :: Maybe Resolution |
@@ -67,6 +69,8 @@ instance FromJSON GalleryConfig where | |||
67 | <*> v .:? "excludedDirectories" .!= [] | 69 | <*> v .:? "excludedDirectories" .!= [] |
68 | <*> v .:? "includedFiles" .!= ["*"] | 70 | <*> v .:? "includedFiles" .!= ["*"] |
69 | <*> v .:? "excludedFiles" .!= [] | 71 | <*> v .:? "excludedFiles" .!= [] |
72 | <*> v .:? "includedTags" .!= ["*"] | ||
73 | <*> v .:? "excludedTags" .!= [] | ||
70 | <*> v .:? "tagsFromDirectories" .!= (TagsFromDirectoriesConfig 0 "") | 74 | <*> v .:? "tagsFromDirectories" .!= (TagsFromDirectoriesConfig 0 "") |
71 | <*> v .:? "thumbnailMaxResolution" .!= (Resolution 400 300) | 75 | <*> v .:? "thumbnailMaxResolution" .!= (Resolution 400 300) |
72 | <*> v .:? "pictureMaxResolution" | 76 | <*> v .:? "pictureMaxResolution" |
diff --git a/compiler/src/Input.hs b/compiler/src/Input.hs index 75d1ed3..6ed7471 100644 --- a/compiler/src/Input.hs +++ b/compiler/src/Input.hs | |||
@@ -19,7 +19,7 @@ | |||
19 | module Input | 19 | module Input |
20 | ( decodeYamlFile | 20 | ( decodeYamlFile |
21 | , Sidecar(..) | 21 | , Sidecar(..) |
22 | , InputTree(..), readInputTree | 22 | , InputTree(..), readInputTree, filterInputTree |
23 | ) where | 23 | ) where |
24 | 24 | ||
25 | 25 | ||
@@ -132,3 +132,14 @@ readInputTree (AnchoredFSNode anchor root@Dir{}) = mkDirNode root | |||
132 | 132 | ||
133 | findThumbnail :: [FSNode] -> Maybe Path | 133 | findThumbnail :: [FSNode] -> Maybe Path |
134 | findThumbnail = (fmap Files.path) . (find isThumbnail) | 134 | findThumbnail = (fmap Files.path) . (find isThumbnail) |
135 | |||
136 | -- | Filters an InputTree. The root is always returned. | ||
137 | filterInputTree :: (InputTree -> Bool) -> InputTree -> InputTree | ||
138 | filterInputTree cond = filterNode | ||
139 | where | ||
140 | filterNode :: InputTree -> InputTree | ||
141 | filterNode inputFile@InputFile{} = inputFile | ||
142 | filterNode inputDir@InputDir{items} = | ||
143 | filter cond items | ||
144 | & map filterNode | ||
145 | & \curatedItems -> inputDir { items = curatedItems } :: InputTree | ||
diff --git a/example/src/gallery.yaml b/example/src/gallery.yaml index c4a5077..dba6b39 100644 --- a/example/src/gallery.yaml +++ b/example/src/gallery.yaml | |||
@@ -11,13 +11,16 @@ includedFiles: | |||
11 | #excludedFiles: | 11 | #excludedFiles: |
12 | # - "*.md" | 12 | # - "*.md" |
13 | 13 | ||
14 | tagsFromDirectories: | 14 | #includedTags: ["*"] |
15 | fromParents: 0 # default | 15 | #excludedTags: [] |
16 | prefix: '' # default | ||
17 | 16 | ||
18 | thumbnailMaxResolution: | 17 | #tagsFromDirectories: |
19 | width: 400 # default | 18 | # fromParents: 0 |
20 | height: 300 # default | 19 | # prefix: '' |
20 | |||
21 | #thumbnailMaxResolution: | ||
22 | # width: 400 | ||
23 | # height: 300 | ||
21 | 24 | ||
22 | pictureMaxResolution: | 25 | pictureMaxResolution: |
23 | width: 1024 | 26 | width: 1024 |