This CL can be used to compare the style of nixpkgs-fmt against other formatters (nixpkgs, alejandra). Change-Id: I87c6abff6bcb546b02ead15ad0405f81e01b6d9e Reviewed-on: https://cl.tvl.fyi/c/depot/+/4397 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org> Reviewed-by: lukegb <lukegb@tvl.fyi> Reviewed-by: wpcarro <wpcarro@gmail.com> Reviewed-by: Profpatsch <mail@profpatsch.de> Reviewed-by: kanepyork <rikingcoding@gmail.com> Reviewed-by: tazjin <tazjin@tvl.su> Reviewed-by: cynthia <cynthia@tvl.fyi> Reviewed-by: edef <edef@edef.eu> Reviewed-by: eta <tvl@eta.st> Reviewed-by: grfn <grfn@gws.fyi>
		
			
				
	
	
		
			143 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ depot, ... }:
 | 
						|
 | 
						|
let
 | 
						|
  inherit (depot.third_party.nixpkgs)
 | 
						|
    lib
 | 
						|
    ;
 | 
						|
 | 
						|
  inherit (depot.users.sterni.nix)
 | 
						|
    url
 | 
						|
    fun
 | 
						|
    string
 | 
						|
    ;
 | 
						|
 | 
						|
  inherit (depot.web.bubblegum)
 | 
						|
    pathInfo
 | 
						|
    scriptName
 | 
						|
    respond
 | 
						|
    absolutePath
 | 
						|
    ;
 | 
						|
 | 
						|
  # substituted using substituteAll in default.nix
 | 
						|
  blogdir = "@blogdir@";
 | 
						|
  # blogdir = toString ./posts; # for local testing
 | 
						|
 | 
						|
  parseDate = post:
 | 
						|
    let
 | 
						|
      matched = builtins.match "/?([0-9]+)-([0-9]+)-([0-9]+)-.+" post;
 | 
						|
    in
 | 
						|
    if matched == null
 | 
						|
    then [ 0 0 0 ]
 | 
						|
    else builtins.map builtins.fromJSON matched;
 | 
						|
 | 
						|
  parseTitle = post:
 | 
						|
    let
 | 
						|
      matched = builtins.match "/?[0-9]+-[0-9]+-[0-9]+-(.+).html" post;
 | 
						|
    in
 | 
						|
    if matched == null
 | 
						|
    then "no title"
 | 
						|
    else builtins.head matched;
 | 
						|
 | 
						|
  dateAtLeast = a: b:
 | 
						|
    builtins.all fun.id
 | 
						|
      (lib.zipListsWith (partA: partB: partA >= partB) a b);
 | 
						|
 | 
						|
  byPostDate = a: b:
 | 
						|
    dateAtLeast (parseDate a) (parseDate b);
 | 
						|
 | 
						|
  posts = builtins.sort byPostDate
 | 
						|
    (builtins.attrNames
 | 
						|
      (lib.filterAttrs (_: v: v == "regular")
 | 
						|
        (builtins.readDir blogdir)));
 | 
						|
 | 
						|
  generic = { title, inner, ... }: ''
 | 
						|
    <!doctype html>
 | 
						|
    <html>
 | 
						|
      <head>
 | 
						|
        <meta charset="utf-8">
 | 
						|
        <title>${title}</title>
 | 
						|
        <style>a:link, a:visited { color: blue; }</style>
 | 
						|
      </head>
 | 
						|
      <body>
 | 
						|
      ${inner}
 | 
						|
      </body>
 | 
						|
    </html>
 | 
						|
  '';
 | 
						|
 | 
						|
  index = posts: ''
 | 
						|
    <main>
 | 
						|
      <h1>blog posts</h1>
 | 
						|
      <ul>
 | 
						|
  '' + lib.concatMapStrings
 | 
						|
    (post: ''
 | 
						|
      <li>
 | 
						|
        <a href="${absolutePath (url.encode {} post)}">${parseTitle post}</a>
 | 
						|
      </li>
 | 
						|
    '')
 | 
						|
    posts + ''
 | 
						|
      </ul>
 | 
						|
    </main>
 | 
						|
  '';
 | 
						|
 | 
						|
  formatDate =
 | 
						|
    let
 | 
						|
      # Assume we never deal with years < 1000
 | 
						|
      formatDigit = d: string.fit
 | 
						|
        {
 | 
						|
          char = "0";
 | 
						|
          width = 2;
 | 
						|
        }
 | 
						|
        (toString d);
 | 
						|
    in
 | 
						|
    lib.concatMapStringsSep "-" formatDigit;
 | 
						|
 | 
						|
  post = title: post: ''
 | 
						|
    <main>
 | 
						|
      <h1>${title}</h1>
 | 
						|
      <div id="content">
 | 
						|
        ${builtins.readFile (blogdir + "/" + post)}
 | 
						|
      </div>
 | 
						|
    </main>
 | 
						|
    <footer>
 | 
						|
      <p>Posted on ${formatDate (parseDate post)}</p>
 | 
						|
      <nav><a href="${scriptName}">index</a></nav>
 | 
						|
    </footer>
 | 
						|
  '';
 | 
						|
 | 
						|
  validatePathInfo = pathInfo:
 | 
						|
    let
 | 
						|
      chars = string.toChars pathInfo;
 | 
						|
    in
 | 
						|
    builtins.length chars > 1
 | 
						|
    && !(builtins.elem "/" (builtins.tail chars));
 | 
						|
 | 
						|
  response =
 | 
						|
    if pathInfo == "/"
 | 
						|
    then {
 | 
						|
      title = "blog";
 | 
						|
      status = 200;
 | 
						|
      inner = index posts;
 | 
						|
    }
 | 
						|
    else if !(validatePathInfo pathInfo)
 | 
						|
    then {
 | 
						|
      title = "Bad Request";
 | 
						|
      status = 400;
 | 
						|
      inner = "No slashes in post names 😡";
 | 
						|
    }
 | 
						|
    # CGI should already url.decode for us
 | 
						|
    else if builtins.pathExists (blogdir + "/" + pathInfo)
 | 
						|
    then rec {
 | 
						|
      title = parseTitle pathInfo;
 | 
						|
      status = 200;
 | 
						|
      inner = post title pathInfo;
 | 
						|
    } else {
 | 
						|
      title = "Not Found";
 | 
						|
      status = 404;
 | 
						|
      inner = "<h1>404 — not found</h1>";
 | 
						|
    };
 | 
						|
in
 | 
						|
respond response.status
 | 
						|
{
 | 
						|
  "Content-type" = "text/html";
 | 
						|
}
 | 
						|
  (generic response)
 |