#!/usr/bin/env nu # Linkify site conventions in blog markdown source: # # ontoref / Ontoref → (brand mention, case-preserving) # ADR-NNN → ADR-NNN (decision deep-link) # # Operates on the MARKDOWN SOURCE (not the generated HTML) so the change survives # every `just content` regeneration. Both rewrites are idempotent via lookarounds: # an already-wrapped mention (preceded by `>` / followed by ``) is left as-is. # # Skipped, so code and metadata never get a stray link: # - YAML frontmatter (between the leading --- delimiters) # - fenced code blocks (``` … ```) # - inline code spans (`…`) # - headings (lines beginning with #) # - compound identifiers: ontoref-daemon, ontoref/dist, .ontoref, /adr/038 (lookarounds) # # Usage (from outreach/site): # nu scripts/build/linkify-site.nu # default glob # nu scripts/build/linkify-site.nu site/content/blog/**/*.md # nu scripts/build/linkify-site.nu --check # CI gate, no writes const LINK = '${n}' const WORD = '(?\w./-])(?[Oo]ntoref)(?![<\w./-])' const ADR_LINK = 'ADR-${num}' const ADR_WORD = '(?/\w-])ADR-(?\d+)(?!)' # Apply both site rewrites outside inline-code spans on a single line. def linkify-line [line: string]: nothing -> string { $line | split row '`' | enumerate | each {|it| if ($it.index mod 2) == 0 { $it.item | str replace --all --regex $WORD $LINK | str replace --all --regex $ADR_WORD $ADR_LINK } else { $it.item } } | str join '`' } def main [ pattern: string = "site/content/blog/**/*.md" --check # report posts that WOULD change and exit non-zero; never writes ] { let files = (glob $pattern | sort) mut changed = 0 for f in $files { let lines = (open --raw $f | lines) mut out = [] mut in_front = false mut in_fence = false mut idx = 0 for line in $lines { let trimmed = ($line | str trim) # Frontmatter: a leading --- opens it, the next --- closes it. if $trimmed == "---" and not $in_fence { if $idx == 0 { $in_front = true } else if $in_front { $in_front = false } $out = ($out | append $line) $idx = ($idx + 1) continue } if ($trimmed | str starts-with '```') { $in_fence = (not $in_fence) $out = ($out | append $line) $idx = ($idx + 1) continue } if $in_front or $in_fence or ($trimmed | str starts-with '#') { $out = ($out | append $line) $idx = ($idx + 1) continue } $out = ($out | append (linkify-line $line)) $idx = ($idx + 1) } let result = ($out | str join "\n") let original = (open --raw $f) # Preserve a trailing newline if the source had one. let final = if ($original | str ends-with "\n") { $result + "\n" } else { $result } if $final != $original { if $check { print $" ($f | path basename): unlinked site mentions pending" } else { $final | save -f $f print $" ($f | path basename): linked" } $changed = ($changed + 1) } } if $check { if $changed > 0 { error make { msg: $"linkify-site --check: ($changed) post\(s\) have unlinked site mentions — run `just content`" } } print "linkify-site --check: all posts clean" } else { print $"linkify-site: ($changed) file\(s\) updated" } }