Browse Source

basic (hacky) working static generator

Getty Ritter 2 years ago
commit
c15c1cfe68
11 changed files with 312 additions and 0 deletions
  1. 3 0
      .gitignore
  2. 24 0
      BUILD.bazel
  3. 22 0
      WORKSPACE
  4. 63 0
      generate.py
  5. 66 0
      projects.yaml
  6. 8 0
      pyvenv.cfg
  7. 3 0
      requirements.txt
  8. 61 0
      static/main.css
  9. 17 0
      static/main.js
  10. BIN
      static/raleway.ttf
  11. 45 0
      templates/main.mustache

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+bin
+lib
+bazel-*

+ 24 - 0
BUILD.bazel

@@ -0,0 +1,24 @@
+load("@rules_python//python:defs.bzl", "py_binary")
+load("@deps//:requirements.bzl", "requirement")
+
+py_binary(
+    name = "generate",
+    srcs = ["generate.py"],
+    deps = [
+        requirement("chevron"),
+        requirement("markdown"),
+        requirement("PyYAML"),
+    ]
+)
+
+genrule(
+    name = "out",
+    srcs = [
+        ":projects.yaml",
+        ":static",
+        ":templates",
+    ],
+    tools = [":generate"],
+    outs = ["output"],
+    cmd = "$(location :generate) $(location :projects.yaml) $(location :static) $(location :templates) $(location output)",
+)

+ 22 - 0
WORKSPACE

@@ -0,0 +1,22 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+    name = "rules_python",
+    sha256 = "9fcf91dbcc31fde6d1edb15f117246d912c33c36f44cf681976bd886538deba6",
+    strip_prefix = "rules_python-0.8.0",
+    url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.8.0.tar.gz",
+)
+
+http_archive(
+    name = "io_bazel_rules_docker",
+    sha256 = "85ffff62a4c22a74dbd98d05da6cf40f497344b3dbf1e1ab0a37ab2a1a6ca014",
+    strip_prefix = "rules_docker-0.23.0",
+    urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.23.0/rules_docker-v0.23.0.tar.gz"],
+)
+
+load("@rules_python//python:pip.bzl", "pip_install")
+
+pip_install(
+   name = "deps",
+   requirements = "//:requirements.txt",
+)

+ 63 - 0
generate.py

@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+
+import chevron
+import datetime
+import os
+import markdown
+import shutil
+import sys
+import tempfile
+import yaml
+
+def main(projects_yaml, static_dir, template_dir, output_file=None):
+    with open(projects_yaml) as f:
+        project_data = yaml.safe_load(f)
+
+    project_data['header'] = markdown.markdown(project_data['header'])
+    for p in project_data['projects']:
+        p['text'] = markdown.markdown(p['text'])
+        for s in p.get('stuff', ()):
+            s['text'] = markdown.markdown(s['text'])
+
+    with open(os.path.join(static_dir, 'main.css')) as f:
+        css = f.read()
+    with open(os.path.join(static_dir, 'main.js')) as f:
+        javascript = f.read()
+
+    with open(os.path.join(template_dir, 'main.mustache')) as f:
+        template = f.read()
+
+    year = datetime.datetime.now().year
+
+    index_html = chevron.render(
+        template=template,
+        data={
+            'css': css,
+            'javascript': javascript,
+            'project_data': project_data,
+            'copyright': f'© {year} Getty Ritter'
+        },
+    )
+
+    if not output_file or output_file == '-':
+        print(index_html)
+        return
+
+    with tempfile.TemporaryDirectory() as tmpdir:
+        with open(os.path.join(tmpdir, 'index.html'), 'w') as f:
+            print(index_html, file=f)
+        shutil.copyfile(
+            os.path.join(static_dir, 'raleway.ttf'),
+            os.path.join(tmpdir, 'raleway.ttf'),
+        )
+        shutil.make_archive('output', 'zip', tmpdir)
+        shutil.move('output.zip', output_file)
+
+if __name__ == '__main__':
+    if len(sys.argv) not in (4, 5):
+        print(
+            f"{sys.argv[0]}: [project.yaml] [static/] [templates/] [output-zip]",
+            file=sys.stderr,
+        )
+        sys.exit(1)
+    main(*sys.argv[1:])

+ 66 - 0
projects.yaml

@@ -0,0 +1,66 @@
+header: >
+  I'm Getty and I start a lot of stuff and finish very little of
+  it. Here's some of that stuff.
+
+  If you want to contact me, send me email at **gdritter at
+  infinitenegativeutility dot com**. You can also find me on [Twitter
+  at @aisamanra](https://twitter.com/aisamanra) and [Mastodon as
+  aysamanra@sometimes.when.computer](https://sometimes.when.computer/@aysamanra).
+projects:
+  - name: programming
+    text: >
+      In addition to doing professional, mostly
+      language-and-tooling-related work—currently on the ruby-infra
+      team at Stripe—I also have some tools and libraries I maintain.
+    stuff:
+      - name: Lament Configuration
+        text: >
+          [Lament
+          Configuration](https://github.com/aisamanra/lament-configuration)
+          is a self-hosted bookmarking service, inspired by Pinboard
+          but tailored to the way I want to track links. My own
+          running instance can be found at
+          [remember.when.computer](https://remember.when.computer/u/gdritter).
+      - name: Apicius
+        text: >
+          whoo
+      - name: config-ini
+        text: >
+          [config-ini](https://github.com/aisamanra/config-ini) is a
+          Haskell library designed for declaratively parsing,
+          serializing, and updating INI files.
+      - name: s-cargot
+        text: >
+          [s-cargot](https://github.com/aisamanra/s-cargot) is a
+          Haskell library for generically serializing and
+          deserializing s-expressions, designed for flexibility over
+          speed.
+  - name: art
+    text: >
+      I like doing art in various media: in physical media, I like
+      sketching, watercolors, block printing and other printmaking
+      techniques, and sporadically modeling with clay, while in
+      digital media, I do sketching, pixel art, vector graphics work,
+      and a bit of 3D modeling. I've got a separate Twitter account I
+      use for occasionally posting art, which can be found at
+      [@uzhdanra](https://twitter.com/uzhdanra).
+  - name: design
+    text: >
+      I have some projects which are information- or graphic-design
+      related, and others that are about designing physical objects
+      for my own use. As of right now, much of my physical design work
+      is done with the help of a laser-cutter.
+  - name: writing
+    text: >
+      I write a lot of non-fiction blog posts, and I also write some
+      fiction, relatively little of which I've made available publicly
+      (yet!)
+  - name: games
+    text: >
+      I do some tabletop game design, and aspirationally would like to
+      do more video game writing. To date I've published relatively
+      few finished game projects, but I'd like to change that going
+      forward.
+    stuff:
+      - name: Logomancy
+        text: blah

+ 8 - 0
pyvenv.cfg

@@ -0,0 +1,8 @@
+home = /usr
+implementation = CPython
+version_info = 3.10.4.final.0
+virtualenv = 20.13.1
+include-system-site-packages = false
+base-prefix = /usr
+base-exec-prefix = /usr
+base-executable = /usr/bin/python3

+ 3 - 0
requirements.txt

@@ -0,0 +1,3 @@
+chevron==0.14.0
+Markdown==3.3.6
+PyYAML==6.0

+ 61 - 0
static/main.css

@@ -0,0 +1,61 @@
+@font-face {
+    font-family: raleway;
+    src: url("raleway.ttf");
+}
+
+body {
+    font-family: "Roboto", "Helvetica", "Arial", sans-serif;
+    background-color: #ffffff;
+    color: #111111;
+}
+
+.logo {
+    text-align: center;
+}
+
+h1, h2 {
+    font-family: raleway;
+}
+
+.main {
+    background-color: #eeeeee;
+    width: 800px;
+    margin-left: auto;
+    margin-right: auto;
+    margin-bottom: 20px;
+    padding-top: 10px;
+    padding-bottom: 20px;
+    padding-left: 40px;
+    padding-right: 40px;
+}
+
+.header {
+    width: 80%;
+    margin-left: auto;
+    margin-right: auto;
+}
+
+.footer {
+    padding: 2em;
+    text-align: center;
+}
+
+.chunk {
+    width: 80%;
+    border: 1px solid black;
+    margin-left: auto;
+    margin-right: auto;
+    margin-top: 1em;
+    padding-bottom: 1em;
+    padding-left: 2em;
+    padding-right: 2em;
+}
+
+.showmore {
+    text-align: center;
+    font-family: raleway;
+}
+
+.item {
+    display: none;
+}

+ 17 - 0
static/main.js

@@ -0,0 +1,17 @@
+window.onload = () => {
+  let buttons = document.querySelectorAll(".showmore");
+  let toggles = {};
+  for (let b of buttons) {
+    toggles[b] = false;
+    b.onclick = (elem, thing) => {
+      for (let i of b.parentElement.querySelectorAll(".item")) {
+        if (toggles[b]) {
+          i.style.display = 'none';
+        } else {
+          i.style.display = 'block';
+        }
+      }
+      toggles[b] = !toggles[b];
+    };
+  }
+};

BIN
static/raleway.ttf


+ 45 - 0
templates/main.mustache

@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <style type="text/css">
+     {{{css}}}
+    </style>
+    <script type="application/javascript">
+     {{{javascript}}}
+    </script>
+
+    <title>G. D. Ritter</title>
+  </head>
+
+  <body>
+    <div class="logo">
+      <h1>G. D. Ritter</h1>
+    </div>
+
+    {{#project_data}}
+      <div class="header">
+        {{{header}}}
+      </div>
+      <div class="contents">
+        {{#projects}}
+          <div class="chunk">
+            <h1 id="name">{{name}}</h1>
+            <p>{{{text}}}</p>
+            <div class="stuff">
+              <div class="showmore">[show more]</div>
+              {{#stuff}}
+                <div class="item">
+                  <h2>{{name}}</h2>
+                  <p>{{{text}}}</p>
+                </div>
+              {{/stuff}}
+            </div>
+          </div>
+        {{/projects}}
+      </div>
+    {{/project_data}}
+    <div class="footer">
+      {{copyright}}
+    </div>
+  </body>
+</html>