forked from fediversity/fediversity
		
	override page template for articles
This commit is contained in:
		
							parent
							
								
									00e3cfcb52
								
							
						
					
					
						commit
						9b74458a8c
					
				
					 2 changed files with 57 additions and 35 deletions
				
			
		| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
let
 | 
			
		||||
  cfg = config;
 | 
			
		||||
  inherit (lib) mkOption types;
 | 
			
		||||
  inherit (types) submodule;
 | 
			
		||||
 | 
			
		||||
  # https://html.spec.whatwg.org/multipage/dom.html#content-models
 | 
			
		||||
  # https://html.spec.whatwg.org/multipage/dom.html#kinds-of-content
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +44,7 @@ let
 | 
			
		|||
 | 
			
		||||
  # options with types for all the defined DOM elements
 | 
			
		||||
  element-types = lib.mapAttrs
 | 
			
		||||
    (name: value: mkOption { type = types.submodule value; })
 | 
			
		||||
    (name: value: mkOption { type = submodule value; })
 | 
			
		||||
    elements;
 | 
			
		||||
 | 
			
		||||
  # attrset of categories, where values are module options with the type of the
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +53,7 @@ let
 | 
			
		|||
    genAttrs
 | 
			
		||||
      content-categories
 | 
			
		||||
      (category:
 | 
			
		||||
        (mapAttrs (_: e: mkOption { type = types.submodule e; })
 | 
			
		||||
        (mapAttrs (_: e: mkOption { type = submodule e; })
 | 
			
		||||
          # HACK: don't evaluate the submodule types, just grab the config directly
 | 
			
		||||
          (filterAttrs (_: e: elem category (e { name = "dummy"; config = { }; }).config.categories) elements))
 | 
			
		||||
      );
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +119,7 @@ let
 | 
			
		|||
 | 
			
		||||
  mkAttrs = attrs: with lib;
 | 
			
		||||
    mkOption {
 | 
			
		||||
      type = types.submodule {
 | 
			
		||||
      type = submodule {
 | 
			
		||||
        options = global-attrs // attrs;
 | 
			
		||||
      };
 | 
			
		||||
      default = { };
 | 
			
		||||
| 
						 | 
				
			
			@ -147,12 +148,21 @@ let
 | 
			
		|||
 | 
			
		||||
  print-element = name: attrs: content:
 | 
			
		||||
    with lib;
 | 
			
		||||
    # TODO: be smarter about content to save some space and repetition at the call sites
 | 
			
		||||
    squash (trim ''
 | 
			
		||||
      <${name}${print-attrs attrs}>
 | 
			
		||||
        ${lib.indent "  " content}
 | 
			
		||||
      </${name}>
 | 
			
		||||
    '');
 | 
			
		||||
 | 
			
		||||
  toString-unwrap = e:
 | 
			
		||||
    with lib;
 | 
			
		||||
    if isAttrs e
 | 
			
		||||
    then toString (head (attrValues e))
 | 
			
		||||
    else if isList e
 | 
			
		||||
    then toString (map toString-unwrap e)
 | 
			
		||||
    else e;
 | 
			
		||||
 | 
			
		||||
  elements = rec {
 | 
			
		||||
    document = { ... }: {
 | 
			
		||||
      imports = [ element ];
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +216,7 @@ let
 | 
			
		|||
        # https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag#viewport_width_and_screen_width
 | 
			
		||||
        # this should not exist and no one should ever have to think about it
 | 
			
		||||
        meta.viewport = mkOption {
 | 
			
		||||
          type = types.submodule ({ ... }: {
 | 
			
		||||
          type = submodule ({ ... }: {
 | 
			
		||||
            # TODO: figure out how to render only non-default values
 | 
			
		||||
            options = {
 | 
			
		||||
              width = mkOption {
 | 
			
		||||
| 
						 | 
				
			
			@ -422,21 +432,13 @@ let
 | 
			
		|||
 | 
			
		||||
      config.categories = [ ];
 | 
			
		||||
      config.__toString = self: with lib;
 | 
			
		||||
        print-element name self.attrs (
 | 
			
		||||
          join "\n" (map
 | 
			
		||||
            (e:
 | 
			
		||||
              if isAttrs e
 | 
			
		||||
              then toString (lib.head (attrValues e))
 | 
			
		||||
              else e
 | 
			
		||||
            )
 | 
			
		||||
            self.content)
 | 
			
		||||
        );
 | 
			
		||||
        print-element name self.attrs (join "\n" (map toString-unwrap self.content));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    section = { config, name, ... }: {
 | 
			
		||||
      imports = [ element ];
 | 
			
		||||
      options = {
 | 
			
		||||
        # setting to an attribute set will wrap the section in <section>
 | 
			
		||||
        # setting to an attribute set will wrap the section in `<section>`
 | 
			
		||||
        attrs = mkOption {
 | 
			
		||||
          type = with types; nullOr (submodule { options = global-attrs; });
 | 
			
		||||
          default = null;
 | 
			
		||||
| 
						 | 
				
			
			@ -450,14 +452,18 @@ let
 | 
			
		|||
          #      such an outline is rather meaningless without headings for navigation,
 | 
			
		||||
          #      which is why we enforce headings in sections.
 | 
			
		||||
          #      arguably, and this is encoded here, a section *is defined* by its heading.
 | 
			
		||||
          type = with types; submodule ({ ... }: {
 | 
			
		||||
          type = with types; submodule ({ config, ... }: {
 | 
			
		||||
            imports = [ element ];
 | 
			
		||||
            options = {
 | 
			
		||||
              attrs = mkAttrs { };
 | 
			
		||||
              # TODO: make `before`/`after` wrap the heading in `<hgroup>` if non-empty
 | 
			
		||||
              # setting to an attribute set will wrap the section in `<hgroup>`
 | 
			
		||||
              hgroup.attrs = mkOption {
 | 
			
		||||
                type = with types; nullOr (submodule { options = global-attrs; });
 | 
			
		||||
                default = with lib; mkIf (!isNull config.before || !isNull config.after) { };
 | 
			
		||||
              };
 | 
			
		||||
              # https://html.spec.whatwg.org/multipage/sections.html#the-hgroup-element
 | 
			
		||||
              before = mkOption {
 | 
			
		||||
                type = with types; listOf (attrTag ({ inherit p; } // categories.scripting));
 | 
			
		||||
                type = with types; listOf (attrTag ({ inherit (element-types) p; } // categories.scripting));
 | 
			
		||||
                default = [ ];
 | 
			
		||||
              };
 | 
			
		||||
              content = mkOption {
 | 
			
		||||
| 
						 | 
				
			
			@ -466,7 +472,7 @@ let
 | 
			
		|||
              };
 | 
			
		||||
              after = mkOption {
 | 
			
		||||
                type = with types;
 | 
			
		||||
                  listOf (attrTag ({ inherit p; } // categories.scripting));
 | 
			
		||||
                  listOf (attrTag ({ inherit (element-types) p; } // categories.scripting));
 | 
			
		||||
                default = [ ];
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
| 
						 | 
				
			
			@ -489,20 +495,32 @@ let
 | 
			
		|||
        __toString = self: with lib;
 | 
			
		||||
          let
 | 
			
		||||
            n = toString config.heading-level;
 | 
			
		||||
            content = ''<h${n}${print-attrs self.heading.attrs}>${self.heading.content}</h${n}>
 | 
			
		||||
              '' + join "\n" (map
 | 
			
		||||
              (e:
 | 
			
		||||
                if isAttrs e
 | 
			
		||||
                then toString (lib.head (attrValues e))
 | 
			
		||||
                else e
 | 
			
		||||
              )
 | 
			
		||||
              self.content);
 | 
			
		||||
            heading = ''<h${n}${print-attrs self.heading.attrs}>${self.heading.content}</h${n}>'';
 | 
			
		||||
            hgroup = with lib; print-element "hgroup" self.heading.hgroup.attrs (squash ''
 | 
			
		||||
              ${optionalString (!isNull self.heading.before) (toString-unwrap self.heading.before)}
 | 
			
		||||
              ${heading}
 | 
			
		||||
              ${optionalString (!isNull self.heading.after) (toString-unwrap self.heading.after)}
 | 
			
		||||
            '');
 | 
			
		||||
            content = if isNull self.heading.hgroup.attrs then heading else hgroup
 | 
			
		||||
              + join "\n" (map toString-unwrap self.content);
 | 
			
		||||
          in
 | 
			
		||||
          if !isNull self.attrs
 | 
			
		||||
          then print-element name self.attrs content
 | 
			
		||||
          else content;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    p = { name, ... }: {
 | 
			
		||||
      imports = [ element ];
 | 
			
		||||
      options = {
 | 
			
		||||
        attrs = mkAttrs { };
 | 
			
		||||
        content = mkOption {
 | 
			
		||||
          type = with types; either str (listOf (attrTag categories.phrasing));
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      config.categories = [ "flow" "palpable" ];
 | 
			
		||||
      config.__toString = self: print-element name self.attrs (toString self.content);
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,17 +27,21 @@ in
 | 
			
		|||
      };
 | 
			
		||||
    };
 | 
			
		||||
    config.name = lib.slug config.title;
 | 
			
		||||
    config.outputs.html = lib.mkForce (cfg.templates.html.dom {
 | 
			
		||||
    config.outputs.html = lib.mkForce ((cfg.templates.html.page config).override {
 | 
			
		||||
      html = {
 | 
			
		||||
        head = {
 | 
			
		||||
          title.text = config.title;
 | 
			
		||||
          meta.description = config.description;
 | 
			
		||||
          meta.authors = if lib.isList config.author then config.author else [ config.author ];
 | 
			
		||||
          link.canonical = lib.head config.locations;
 | 
			
		||||
        };
 | 
			
		||||
        body.content = [
 | 
			
		||||
        # TODO: make authors always a list
 | 
			
		||||
        head.meta.authors = if lib.isList config.author then config.author else [ config.author ];
 | 
			
		||||
        body.content = lib.mkForce [
 | 
			
		||||
          (cfg.menus.main.outputs.html config)
 | 
			
		||||
          { section.heading.content = config.title; }
 | 
			
		||||
          {
 | 
			
		||||
            section.heading = {
 | 
			
		||||
              # TODO: i18n support
 | 
			
		||||
              # TODO: structured dates
 | 
			
		||||
              before = [{ p.content = "Published ${config.date}"; }];
 | 
			
		||||
              content = config.title;
 | 
			
		||||
              after = [{ p.content = "Written by ${config.author}"; }];
 | 
			
		||||
            };
 | 
			
		||||
          }
 | 
			
		||||
          (cfg.templates.html.markdown { inherit (config) name body; })
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue