forked from fediversity/fediversity
		
	allow prefixing output paths of collection items
This commit is contained in:
		
							parent
							
								
									3505539499
								
							
						
					
					
						commit
						7efd5b8317
					
				
					 10 changed files with 54 additions and 46 deletions
				
			
		|  | @ -5,7 +5,10 @@ in | |||
| { | ||||
|   imports = lib.nixFiles ./.; | ||||
| 
 | ||||
|   collections.news.type = config.content-types.article; | ||||
|   collections.news = { | ||||
|     type = config.content-types.article; | ||||
|     prefixes = [ "news" ]; | ||||
|   }; | ||||
| 
 | ||||
|   pages.index = { link, ... }: { | ||||
|     title = "Fediversity"; | ||||
|  |  | |||
|  | @ -18,9 +18,7 @@ in | |||
|           in | ||||
|           map | ||||
|             (page: { | ||||
|               page = lib.recursiveUpdate page { | ||||
|                 title = "${page.date}: ${page.title}"; | ||||
|               }; | ||||
|               page = lib.recursiveUpdate page { title = "${page.date}: ${page.title}"; }; | ||||
|             }) | ||||
|             (lib.take 3 sorted); | ||||
|       } | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { ... }: | ||||
| { config, lib, ... }: | ||||
| { | ||||
|   collections.news.entry = { | ||||
|   collections.news.entry = { link, ... }: { | ||||
|     title = "Fediversity project publicly announced"; | ||||
|     description = "The Fediversity project has officially been announced"; | ||||
|     date = "2024-01-01"; | ||||
|  |  | |||
|  | @ -52,16 +52,17 @@ rec { | |||
|       inherit (lib) lists; | ||||
| 
 | ||||
|       path1 = subpath.components path1'; | ||||
|       prefix1 = with lib; take (length path1 - 1) path1; | ||||
|       path2 = subpath.components path2'; | ||||
|       prefix2 = with lib; take (length path1 - 1) path2; | ||||
| 
 | ||||
|       commonPrefixLength = with lists; | ||||
|         findFirstIndex (i: i.fst != i.snd) | ||||
|           { fst = null; snd = null; } | ||||
|           (zipLists path1 path2); | ||||
|           (length prefix1) | ||||
|           (zipLists prefix1 prefix2); | ||||
| 
 | ||||
|       relativeComponents = with lists; | ||||
|         [ "." ] ++ (replicate (length path1 - commonPrefixLength - 1) "..") ++ | ||||
|         (drop commonPrefixLength path2); | ||||
|         [ "." ] ++ (replicate (length prefix1 - commonPrefixLength) "..") ++ (drop commonPrefixLength path2); | ||||
|     in | ||||
|     join "/" relativeComponents; | ||||
| 
 | ||||
|  | @ -98,13 +99,7 @@ rec { | |||
|         merge = loc: defs: | ||||
|           map | ||||
|             (def: | ||||
|               let | ||||
|                 merged = lib.mergeDefinitions | ||||
|                   (loc ++ [ "[definition ${toString def.file}]" ]) | ||||
|                   elemType | ||||
|                   [{ inherit (def) file; value = def.value; }]; | ||||
|               in | ||||
|               if merged ? mergedValue then merged.mergedValue else merged.value | ||||
|               elemType.merge (loc ++ [ "[definition ${toString def.file}]" ]) [{ inherit (def) file; value = def.value; }] | ||||
|             ) | ||||
|             defs; | ||||
|         check = elemType.check; | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ in | |||
|           <link rel="canonical" href="${page.outPath}" /> | ||||
|         ''; | ||||
|         body = '' | ||||
|           ${templates.nav { menu = { menu = config.menus.main; }; }} | ||||
|           ${templates.nav { inherit page; menu = { menu = config.menus.main; }; }} | ||||
|           ${builtins.readFile (commonmark page.name page.body)} | ||||
|         ''; | ||||
|       }); | ||||
|  | @ -55,7 +55,7 @@ in | |||
|           } | ||||
|         ''; | ||||
|         body = '' | ||||
|           ${templates.nav { menu = { menu = config.menus.main; }; }} | ||||
|           ${templates.nav { inherit page; menu = { menu = config.menus.main; }; }} | ||||
|           ${builtins.readFile (commonmark page.name page.body)} | ||||
|         ''; | ||||
|       }); | ||||
|  | @ -76,20 +76,13 @@ in | |||
|     let | ||||
|       pages = lib.attrValues config.pages; | ||||
|       collections = with lib; concatMap (collection: collection.entry) (attrValues config.collections); | ||||
|       collections' = with lib; map | ||||
|         ( | ||||
|           entry: recursiveUpdate entry { | ||||
|             locations = map (l: "${entry.collection.name}/${l}") entry.locations; | ||||
|           } | ||||
|         ) | ||||
|         collections; | ||||
|     in | ||||
|     with lib; foldl | ||||
|       (acc: elem: acc // { | ||||
|         "${head elem.locations}" = builtins.toFile "${elem.name}.html" elem.outputs.html; | ||||
|       }) | ||||
|       { } | ||||
|       (pages ++ collections'); | ||||
|       (pages ++ collections); | ||||
| 
 | ||||
|   options.build = mkOption { | ||||
|     description = '' | ||||
|  |  | |||
|  | @ -14,23 +14,23 @@ rec { | |||
|       <body> | ||||
|     </html> | ||||
|   ''; | ||||
|   nav = { menu }: | ||||
|   nav = { page, menu }: | ||||
|     let | ||||
|       render-item = item: | ||||
|         if item ? menu then | ||||
|           '' | ||||
|             <li>${item.menu.label} | ||||
|             ${lib.indent "  " (nav { menu = item; })} | ||||
|             ${lib.indent "  " (nav { inherit page; menu = item; })} | ||||
|           '' | ||||
|         else | ||||
|           if item ? page then ''<li><a href="${item.page}">${item.page.title}</a></li>'' | ||||
|           if item ? page then ''<li><a href="${page.link item.page}">${item.page.title}</a></li>'' | ||||
|           else ''<li><a href="${item.link.url}">${item.link.label}</a></li>'' | ||||
|       ; | ||||
|     in | ||||
|     '' | ||||
|       <nav> | ||||
|         <ul> | ||||
|         ${with lib; indent "    " (join "\n" (map render-item menu.menu.items))} | ||||
|           ${with lib; indent "    " (join "\n" (map render-item menu.menu.items))} | ||||
|         </ul> | ||||
|       </nav> | ||||
|     ''; | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ let | |||
|   cfg = config; | ||||
| in | ||||
| { | ||||
|   content-types. article = { config, collection, ... }: { | ||||
|   content-types.article = { config, collection, ... }: { | ||||
|     imports = [ cfg.content-types.page ]; | ||||
|     options = { | ||||
|       collection = mkOption { | ||||
|  | @ -27,9 +27,6 @@ in | |||
|       }; | ||||
|     }; | ||||
|     config.name = lib.slug config.title; | ||||
|     # TODO: this should be covered by the TBD `link` function instead, | ||||
|     #       taking a historical list of collection names into account | ||||
|     config.outPath = "${collection.name}/${lib.head config.locations}"; | ||||
|     config.outputs.html = lib.mkForce (cfg.templates.html.article cfg config); | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -52,13 +52,25 @@ in | |||
|             type = types.str; | ||||
|             default = name; | ||||
|           }; | ||||
|           entry = mkOption { | ||||
|             description = "An entry in the collection"; | ||||
|             type = types.collection (types.submodule ({ | ||||
|               _module.args.collection = config; | ||||
|               imports = [ config.type ]; | ||||
|             })); | ||||
|           prefixes = mkOption { | ||||
|             description = '' | ||||
|               List of historic output locations for files in the collection | ||||
| 
 | ||||
|               The first element is the canonical location. | ||||
|               All other elements are used to create redirects to the canonical location. | ||||
|             ''; | ||||
|             type = with types; nonEmptyListOf str; | ||||
|             example = [ "." ]; | ||||
|           }; | ||||
|           entry = mkOption | ||||
|             { | ||||
|               description = "An entry in the collection"; | ||||
|               type = types.collection (types.submodule ({ | ||||
|                 imports = [ config.type ]; | ||||
|                 _module.args.collection = config; | ||||
|                 process-locations = ls: with lib; concatMap (l: map (p: "${p}/${l}") config.prefixes) ls; | ||||
|               })); | ||||
|             }; | ||||
|         }; | ||||
|       })); | ||||
|     }; | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ let | |||
|     ; | ||||
| in | ||||
| { | ||||
|   content-types.document = { name, config, link, ... }: { | ||||
|   content-types.document = { name, config, options, link, ... }: { | ||||
|     config._module.args.link = config.link; | ||||
|     options = { | ||||
|       name = mkOption { | ||||
|  | @ -17,7 +17,6 @@ in | |||
|       # TODO: reconsider using `page.outPath` and what to put into `locations`. | ||||
|       #       maybe we can avoid having ".html" suffixes there. | ||||
|       #       since templates can output multiple files, `html` is merely one of many things we *could* produce. | ||||
|       # TODO: make `apply` configurable so one can programmatically modify locations | ||||
|       locations = mkOption { | ||||
|         description = '' | ||||
|           List of historic output locations for the resulting file | ||||
|  | @ -26,11 +25,17 @@ in | |||
|           All other elements are used to create redirects to the canonical location. | ||||
|         ''; | ||||
|         type = with types; nonEmptyListOf str; | ||||
|         apply = config.process-locations; | ||||
|       }; | ||||
|       process-locations = mkOption { | ||||
|         description = "Function to post-process the output locations of contained document"; | ||||
|         type = types.functionTo options.locations.type; | ||||
|         default = lib.id; | ||||
|       }; | ||||
|       link = mkOption { | ||||
|         description = "Helper function for transparent linking to other pages"; | ||||
|         type = with types; functionTo str; | ||||
|         default = target: with lib; relativePath (head config.locations) (head target.locations); | ||||
|         default = target: with lib; relativePath config.outPath target.outPath; | ||||
|       }; | ||||
|       # TODO: may not need it when using `link`; could repurpose it to render the default template | ||||
|       outPath = mkOption { | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| { config, lib, ... }: | ||||
| { config, options, lib, ... }: | ||||
| let | ||||
|   inherit (lib) | ||||
|     mkOption | ||||
|  | @ -7,7 +7,12 @@ let | |||
|   cfg = config; | ||||
|   subtype = baseModule: types.submodule [ | ||||
|     baseModule | ||||
|     { _module.freeformType = types.attrs; } | ||||
|     { | ||||
|       _module.freeformType = types.attrs; | ||||
|       # XXX: this is supposed to be used with a finished value, | ||||
|       #      and we don't want to process locations again. | ||||
|       process-locations = lib.mkForce lib.id; | ||||
|     } | ||||
|   ]; | ||||
| in | ||||
| { | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Valentin Gagarin
							Valentin Gagarin