pkgs: let nixLib = pkgs.lib; toKebabCase = import ./lib/toKebabCase.nix; wordCount = import ./lib/wordCount.nix; charCount = import ./lib/charCount.nix; # Internal-only sortByDate = import ./lib/sortByDate.nix; mkNav = import ./lib/mkNav.nix {lib = nixLib;}; mkCollection = import ./lib/mkCollection.nix {lib = nixLib;}; lib = args: { inherit toKebabCase wordCount charCount; importContent = import ./lib/importContent.nix args; importTemplates = import ./lib/importTemplates.nix; mkRSS = pkgs.callPackage ./lib/mkRSS.nix {}; mkSitemap = pkgs.callPackage ./lib/mkSitemap.nix {}; mkPage = pkgs.callPackage ./lib/mkPage.nix {}; mkHighlightCss = pkgs.callPackage ./lib/mkHighlightCss.nix {}; mkHTML = pkgs.callPackage ./lib/mkHTML.nix { # Declare argument here so it can be accessed via `prev` when the drv is overridden from = "commonmark_x"; }; }; # Joins path segments into an absolute URL, dropping empty segments so a # root ([]) joins to "/" and a leaf never ends up with a doubled slash. joinUrl = parts: let p = builtins.filter (x: x != "") parts; in "/" + builtins.concatStringsSep "/" p; mkDerivation = { content ? {}, static ? null, generateSitemap ? true, metadata ? { title = "Title"; link = "http://127.0.0.1:9999"; description = "Description"; }, pandoc ? {}, lib, }: let sectionNames = builtins.attrNames content; isCollection = name: (content.${name}.collection or null) != null; urlPrefixOf = name: if content.${name}.root or false then [] else [name]; # Drop drafts from each section's page list before anything else. rawSections = builtins.mapAttrs ( _: spec: builtins.filter (p: !(p.draft or false)) spec.pages ) content; # Resolve slug/url and render markdown -> HTML for every page. resolvedSections = builtins.mapAttrs ( name: pages: let spec = content.${name}; urlPrefix = urlPrefixOf name; in map ( page: let sectionPath = page.sectionPath or []; isIndex = page.isSectionIndex or false; slug = page.slug or (lib.toKebabCase page.title); computedUrl = if isIndex then joinUrl (urlPrefix ++ sectionPath) else joinUrl (urlPrefix ++ sectionPath ++ [slug]); url = page.url or computedUrl; pandocCfg = (pandoc // (spec.pandoc or {})) // (page.pandoc or {}); rendered = if page ? content then builtins.readFile "${lib.mkHTML.override (pandocCfg // {source = page.content;})}/page.html" else ""; wordCount = page.wordCount or ( if page ? content then lib.wordCount page.content else 0 ); charCount = page.charCount or ( if page ? content then lib.charCount page.content else 0 ); in page // { inherit slug url wordCount charCount; content = rendered; template = page.template or spec.template; } ) pages ) rawSections; # Sections flagged with `collection` get chronological sort, # next/prev wiring, pagination pages, and tag pages. collectionResults = builtins.listToAttrs (map ( name: { inherit name; value = let spec = content.${name}; sorted = builtins.sort sortByDate resolvedSections.${name}; in mkCollection { posts = sorted; sectionUrl = joinUrl (urlPrefixOf name); paginate = spec.collection.paginate or null; paginationTemplate = spec.collection.paginationTemplate or spec.template; tags = spec.collection.tags or false; tagTemplate = spec.collection.tagTemplate or spec.template; }; } ) (builtins.filter isCollection sectionNames)); pagesOfSection = name: if isCollection name then collectionResults.${name}.posts ++ collectionResults.${name}.extraPages else resolvedSections.${name}; allRenderPages = builtins.concatLists (map pagesOfSection sectionNames); nav = builtins.mapAttrs (_: mkNav) resolvedSections; pageDerivations = map (page: lib.mkPage.override { inherit page nav metadata; }) allRenderPages; rssDerivations = nixLib.concatMap ( name: let spec = content.${name}; in if isCollection name && (spec.collection.rss or true) then let urlPrefix = urlPrefixOf name; rssPath = if urlPrefix == [] then "rss.xml" else "${builtins.concatStringsSep "/" urlPrefix}/rss.xml"; in [ (lib.mkRSS.override { inherit (metadata) title link description; posts = collectionResults.${name}.posts; path = rssPath; }) ] else [] ) (builtins.filter isCollection sectionNames); sitemapDerivations = if generateSitemap then [ (lib.mkSitemap.override { inherit (metadata) link; pages = allRenderPages; }) ] else []; highlightCssDerivations = let generate = pandoc.generateHighlightCss or true; lightStyle = pandoc.highlightStyle or null; darkStyle = pandoc.highlightStyleDark or null; in ( if lightStyle != null && generate then [ (lib.mkHighlightCss.override { style = lightStyle; path = "highlight.css"; }) ] else [] ) ++ ( if darkStyle != null && generate then [ (lib.mkHighlightCss.override { style = darkStyle; path = "highlight-dark.css"; }) ] else [] ); in pkgs.symlinkJoin { name = "website"; paths = pageDerivations ++ rssDerivations ++ sitemapDerivations ++ highlightCssDerivations ++ ( if static != null then [static] else [] ); }; in { inherit lib; mkSite = args: let libWithArgs = lib preArgs; preArgs = args libWithArgs; in # `lib` only needs to be inherited back into the returned attrset when # overriding part of it, otherwise it defaults to the unmodified bundle # passed in. mkDerivation (preArgs // {lib = preArgs.lib or libWithArgs;}); }