Source files

new.sh

#!/bin/sh
set -eu

week="$(date +%Gw%V)"
today="$(date +%Y%m%d)"
clock=""

apply_date() {
    local when="$1" mode="$2"
    case "$when" in
        yesterday) today="$(date -v-1d +%Y%m%d)"; week="$(date -v-1d +%Gw%V)";;
        tomorrow)  today="$(date -v+1d +%Y%m%d)"; week="$(date -v+1d +%Gw%V)";;
        next)      today="$(date -v+1w +%Y%m%d)"; week="$(date -v+1w +%Gw%V)";;
        last)      today="$(date -v-1w +%Y%m%d)"; week="$(date -v-1w +%Gw%V)";;
        +[0-9]*)
            local n="${when#+}"
            if test "$mode" = w; then
                today="$(date -v+"${n}"w +%Y%m%d)"; week="$(date -v+"${n}"w +%Gw%V)"
            else
                today="$(date -v+"${n}"d +%Y%m%d)"; week="$(date -v+"${n}"d +%Gw%V)"
            fi;;
        -[0-9]*)
            local n="${when#-}"
            if test "$mode" = w; then
                today="$(date -v-"${n}"w +%Y%m%d)"; week="$(date -v-"${n}"w +%Gw%V)"
            else
                today="$(date -v-"${n}"d +%Y%m%d)"; week="$(date -v-"${n}"d +%Gw%V)"
            fi;;
        [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
            today="$when"
            week="$(date -jf %Y%m%d "$when" +%Gw%V)";;
        *) echo "Unknown date offset: $when" >&2; exit 1;;
    esac
    clock="$(date -jf %Y%m%d "$today" "+%Y-%m-%dT12:00:00.00%z" | sed 's/\(..\)$/:\1/')"
}

hugo_new() {
    if test -n "$clock"; then
        set -- --clock "$clock" "$@"
    fi
    exec hugo new content --editor code "$@"
}

usage() {
    cat <<EOF
Usage: $0 <command> [options] [slug]

Commands:
  day [-k kind] [-d when] <slug>    Create a day post (default kind: daypost)
  week [-d when] [slug]             Create a week log (no slug) or week post (with slug)
  page <path>                       Create an arbitrary page

Date offsets (-d):
  yesterday, tomorrow — shift by one day
  next, last          — shift by one week
  +N, -N              — shift by N days (day) or N weeks (week)
  YYYYMMDD            — specific date

Examples (today: $today, week: $week):
  COMMAND                                          CREATES
  $0 day meeting-notes                       log/$week/${today}-meeting-notes/index.md
  $0 day -d yesterday meeting-notes          log/$week/${today}-meeting-notes/index.md
  $0 week                                    log/$week/_index.md
  $0 week projects                           log/$week/projects/index.md
  $0 week -d next                            log/$week/_index.md
  $0 week -d next projects                   log/$week/projects/index.md
  $0 page notes/workstation-setup/index.md   notes/workstation-setup/index.md
EOF
}

case "${1:-}" in
    day)
        shift
        kind=daypost
        while test $# -gt 0; do
            case "$1" in
                -k) kind="$2"; shift 2;;
                -d) apply_date "$2" d; shift 2;;
                -*) echo "Unknown option: $1" >&2; exit 1;;
                *) slug="$1"; shift;;
            esac
        done
        if test -z "${slug:-}"; then
            echo "Usage: $0 day [-k kind] <slug>" >&2
            exit 1
        fi
        hugo_new --kind "$kind" "log/$week/${today}-${slug}/index.md"
        ;;
    week)
        shift
        slug=""
        while test $# -gt 0; do
            case "$1" in
                -d) apply_date "$2" w; shift 2;;
                -*) echo "Unknown option: $1" >&2; exit 1;;
                *) slug="$1"; shift;;
            esac
        done
        if test -z "$slug"; then
            hugo_new --kind weeklog "log/$week/_index.md"
        else
            hugo_new --kind weekpost "log/$week/${slug}/index.md"
        fi
        ;;
    page)
        shift
        if test -z "${1:-}"; then
            echo "Usage: $0 page <path>" >&2
            exit 1
        fi
        hugo_new "$1"
        ;;
    -h|--help)
        usage
        exit 0
        ;;
    *)
        usage >&2
        exit 1
        ;;
esac

vscode.settings.json

{
  "vim.leader": "<space>",
  "vim.normalModeKeyBindingsNonRecursive": [
    {
      "before": ["<leader>", "H"],
      "commands": [
        {
          "command": "workbench.action.tasks.runTask",
          "args": "Open hugo page in browser"
        }
      ]
    }
  ]
}

vscode.tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Open hugo page in browser",
      "type": "shell",
      "command": "bash",
      "args": [
        "-c",
        "FILE='${relativeFile}'; if [[ $FILE != content/*.md ]]; then exit 0; fi; P=${FILE#content/}; P=${P%.md}; P=${P%_index}; P=${P%index}; P=${P%/}; open \"http://localhost:1313/$P/\""
      ],
      "presentation": {
        "reveal": "never",
        "panel": "shared",
        "clear": true
      },
      "problemMatcher": []
    }
  ]
}

archetypes.daypost.md

---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
tags:
- daypost
---

archetypes.weeklog.md

---
{{- define "isoDateYear" -}}
{{- /* Return the ISO year based on the week number */ -}}
{{ $wd := sub (int now.Weekday) 1 }}{{ if lt $wd 0 }}{{ $wd = 6 }}{{ end }}{{ $thu := now.AddDate 0 0 (sub 3 $wd) }}{{ $week := add 1 (div (sub $thu.YearDay 1) 7) }}{{ printf "%d" $thu.Year }}
{{- end -}}

{{- define "isoDateWeek" -}}
{{- /* Return the ISO week number */ -}}
{{ $wd := sub (int now.Weekday) 1 }}{{ if lt $wd 0 }}{{ $wd = 6 }}{{ end }}{{ $thu := now.AddDate 0 0 (sub 3 $wd) }}{{ $week := add 1 (div (sub $thu.YearDay 1) 7) }}{{ printf "%02d" $week }}
{{- end -}}

title: {{ template "isoDateYear" }} Week {{ template "isoDateWeek" }}
date: {{ .Date }} # Set to the date of the week's Monday
isoDate:
  Year: {{ template "isoDateYear" }}
  Week: {{ template "isoDateWeek" }}
type: weeklog
---

## Weekposts

{{< weekposts >}}

## Monday

### Goals

...

### Other

...

### Pages

{{< daypostsFromOffset 0 >}}

## Tuesday

### Goals

...

### Other

...

### Pages

{{< daypostsFromOffset 1 >}}

## Wednesday

### Goals

...

### Other

...

### Pages

{{< daypostsFromOffset 2 >}}

## Thursday

### Goals

...

### Other

...

### Pages

{{< daypostsFromOffset 3 >}}

## Friday

### Goals

...

### Other

...

### Pages

{{< daypostsFromOffset 4 >}}

archetypes.weekpost.md

---
{{- define "isoWeekId" -}}
{{- /* Return the ISO year based on the week number */ -}}
{{ $wd := sub (int now.Weekday) 1 }}{{ if lt $wd 0 }}{{ $wd = 6 }}{{ end }}{{ $thu := now.AddDate 0 0 (sub 3 $wd) }}{{ $week := add 1 (div (sub $thu.YearDay 1) 7) }}{{ printf "%dw%02d" $thu.Year $week }}
{{- end -}}

title: '{{ template "isoWeekId" }} {{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
tags:
- weekpost
---

content.user.html

<p>
  This tool generates links to look up users by username.
  It can't know anything about our real directory, so a typo'd user will generate invalid links.
</p>

<style>
#user-info th,
#user-info td {
  text-align: left;
}
#user-info th {
  padding-right: 1em;
}
</style>

<template id="user-template">
  <h2 data-field="username"></h2>
  <table>
    <tr><th>Slack</th><td><a target="_blank" data-field="slack"></a></td></tr>
    <tr><th>Email</th><td><a data-field="email"></a></td></tr>
  </table>
</template>

<div id="user-info">
  <h2>No user</h2>
  <p>Set <code>?u=USERNAME</code> in the URL bar</p>
</div>

<script>
(function() {
  const params = new URLSearchParams(window.location.search);
  const username = params.get('u');

  if (!username) return;

  const template = document.getElementById('user-template');
  const clone = template.content.cloneNode(true);

  clone.querySelector('[data-field="username"]').textContent = username;

  const slack = clone.querySelector('[data-field="slack"]');
  slack.href = `https://example.slack.com/team/${username}`;
  slack.textContent = `@${username}`;

  const emailAddr = `${username}@example.com`;
  const email = clone.querySelector('[data-field="email"]');
  email.href = `mailto:${emailAddr}`;
  email.textContent = emailAddr;

  const container = document.getElementById('user-info');
  container.replaceChildren(clone);
})();
</script>

<!-- -*- mode: html -*- -->

markup.render-link.html


{{- /*
Compute display text for <https://example.com> -style "autolinks".
For recognized services, replace the bare URL with a human-readable label.
*/ -}}
{{- $linkText := .Text }}
{{- $useCite := false }}
{{- if and $u.IsAbs (eq .Text .Destination) }}

  {{- /* GitHub: shorten to org/repo, org/repo#number, or org/repo@commit/path */}}
  {{- if hasPrefix .Destination "https://github.com/" }}
    {{- $path := strings.TrimPrefix "https://github.com/" .Destination }}
    {{- $parts := split $path "/" }}
    {{- $org := index $parts 0 }}
    {{- $repo := index $parts 1 }}
    {{- $text := printf "%s/%s" $org $repo }}
    {{- if and (ge (len $parts) 4) (or (eq (index $parts 2) "issues") (eq (index $parts 2) "pull")) }}
      {{- /* Issue or PR URL: append #number */}}
      {{- $text = printf "%s/%s#%s" $org $repo (index $parts 3) }}
    {{- else if and (ge (len $parts) 4) (or (eq (index $parts 2) "tree") (eq (index $parts 2) "blob")) }}
      {{- /* Tree or blob URL: append @short-hash/subpath */}}
      {{- $hash := index $parts 3 }}
      {{- $short := substr $hash 0 7 }}
      {{- $rest := after 4 $parts }}
      {{- $text = printf "%s/%s@%s/%s" $org $repo $short (delimit $rest "/") }}
    {{- end }}
    {{- $linkText = printf "[GH] %s" $text }}

  {{- /* Confluence wiki: show space key and page title */}}
  {{- else if findRE `^https://example\.atlassian\.net/wiki/spaces/` .Destination }}
    {{- $path := replaceRE `^https://example\.atlassian\.net/wiki/spaces/` "" .Destination }}
    {{- $parts := split $path "/" }}
    {{- $space := index $parts 0 }}
    {{- /* Page title is the 4th path segment; + encodes spaces in Confluence URLs */}}
    {{- $title := index $parts 3 | replaceRE `\+` " " }}
    {{- $linkText = printf "[Confluence: %s] %s" $space $title }}
    {{- $useCite = true }}

  {{- /* Twitter/X profile or tweet; both twitter.com and x.com are supported */}}
  {{- else if or (hasPrefix .Destination "https://twitter.com/") (hasPrefix .Destination "https://x.com/") }}
    {{- $twitterBase := cond (hasPrefix .Destination "https://twitter.com/") "https://twitter.com/" "https://x.com/" }}
    {{- $path := strings.TrimPrefix $twitterBase .Destination }}
    {{- $parts := split $path "/" }}
    {{- $user := index $parts 0 }}
    {{- if and (ge (len $parts) 3) (eq (index $parts 1) "status") }}
      {{- /* Tweet URL: twitter.com/user/status/id */}}
      {{- $linkText = printf "[Twitter] tweet from @%s" $user }}
    {{- else }}
      {{- /* Profile URL: twitter.com/user */}}
      {{- $linkText = printf "[Twitter] @%s" $user }}
    {{- end }}

  {{- /* Wikipedia: convert article slug to title (underscores to spaces) */}}
  {{- else if findRE `^https://[a-z]+\.wikipedia\.org/wiki/` .Destination }}
    {{- $title := replaceRE `^https://[a-z]+\.wikipedia\.org/wiki/` "" .Destination | replaceRE `_` " " }}
    {{- $linkText = printf "[WP] %s" $title }}
    {{- $useCite = true }}

  {{- /* Jira ticket: extract and show the ticket ID (e.g. PROJ-123) */}}
  {{- else if findRE `^https://example\.atlassian\.net/.*[A-Z]+-\d+` .Destination }}
    {{- $ticket := replaceRE `.*?([A-Z]+-\d+).*` "$1" .Destination }}
    {{- $linkText = printf "[Jira] %s" $ticket }}

  {{- end }}
{{- end }}

partials.dayPosts.html

{{- $section := .Section -}}
{{- $start := time (.Date | time.Format "2006-01-02") -}}
{{- $end := $start.AddDate 0 0 1 -}}
{{- $pages := where $section.RegularPages "Date" "ge" $start -}}
{{- $pages = where $pages "Date" "lt" $end -}}
{{- $pages = where $pages "Params.tags" "intersect" (slice "daypost") -}}
{{- if $pages }}
<ul>
  {{- range $pages.ByDate }}
  <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
  {{- end }}
</ul>
{{- else }}
<p>None</p>
{{- end }}

partials.weekPosts.html

{{- $section := .Section -}}
{{- $pages := where $section.RegularPages "Params.tags" "intersect" (slice "weekpost") -}}
{{- if $pages }}
<ul>
  {{- range $pages.ByDate }}
  <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
  {{- end }}
</ul>
{{- else }}
<p>None</p>
{{- end }}

shortcodes.dayPostsFromOffset.html

{{- $offset := .Get 0 | default 0 | int -}}
{{- $date := .Page.Date -}}
{{- $dateWithOffset := $date.AddDate 0 0 $offset -}}
{{- partial "dayposts.html" (dict "Section" .Page.CurrentSection "Date" $dateWithOffset) -}}

shortcodes.link.html

{{ with .Site.GetP|age (.Get 0) }}<a href="{{ .Permalink }}"><cite>{{ .Title }}</cite></a>{{ end }}

shortcodes.u.html

<a class="userlink" href="{{ .Site.BaseURL }}tools/user/?u={{ .Get 0 }}>~{{ .Get 0 }}</a>