{{/* files shortcode — renders a VS Code-style file browser with scaffolding commands. Usage: {{< files name="my-project" >}} {{< file path="app.py" >}} ...contents... {{< /file >}} {{< file path="db/password.txt" >}} secretpassword {{< /file >}} {{< /files >}} Attributes: name required. Project name. Used as the window title and as the top-level directory in the scaffolding commands. */}} {{ with .Inner }}{{/* trigger child rendering */}}{{ end }} {{ $name := trim (.Get "name") " " }} {{ if not $name }} {{- errorf "files shortcode requires a name attribute: %s" .Position -}} {{ end }} {{ $files := .Store.Get "files" }} {{ if not $files }} {{- errorf "files shortcode is empty: %s" .Position -}} {{ end }} {{/* Collect unique parent directories (relative to project root) for mkdir. */}} {{ $dirs := slice }} {{ range $files }} {{ $d := path.Dir .path }} {{ if and (ne $d ".") (not (in $dirs $d)) }} {{ $dirs = $dirs | append $d }} {{ end }} {{ end }} {{/* Build the bash scaffolding command. */}} {{ $bashLines := slice }} {{ if $dirs }} {{ $mkdirPaths := slice }} {{ range $d := $dirs }} {{ $mkdirPaths = $mkdirPaths | append (printf "%s/%s" $name $d) }} {{ end }} {{ $bashLines = $bashLines | append (printf "mkdir -p %s && cd %s" (delimit $mkdirPaths " ") $name) }} {{ else }} {{ $bashLines = $bashLines | append (printf "mkdir %s && cd %s" $name $name) }} {{ end }} {{/* Use an unlikely heredoc delimiter so a file whose content contains a bare `EOF` line (for example, a Dockerfile that itself has a `RUN < %s <<'__DOCKER_DOCS_SCAFFOLD_EOF__'" .path) }} {{ $bashLines = $bashLines | append .content }} {{ $bashLines = $bashLines | append "__DOCKER_DOCS_SCAFFOLD_EOF__" }} {{ end }} {{ $bashScript := delimit $bashLines "\n" }} {{/* Build the PowerShell scaffolding command. */}} {{/* Write files via [System.IO.File]::WriteAllText with an explicit UTF8Encoding($false), so output is UTF-8 without BOM in both Windows PowerShell 5.1 and PowerShell 7+. The built-in `Set-Content -Encoding utf8` emits a BOM on 5.1, which can break Dockerfile `# syntax=` directives and some YAML parsers. */}} {{ $psLines := slice }} {{ $psLines = $psLines | append "# Write files as UTF-8 without BOM. Works on Windows PowerShell 5.1 and PowerShell 7+." }} {{ $psLines = $psLines | append "function WriteFile([string]$Path, [string]$Content) {" }} {{ $psLines = $psLines | append " $full = Join-Path -Path (Get-Location).ProviderPath -ChildPath $Path" }} {{ $psLines = $psLines | append " [System.IO.File]::WriteAllText($full, $Content, [System.Text.UTF8Encoding]::new($false))" }} {{ $psLines = $psLines | append "}" }} {{ $psLines = $psLines | append "" }} {{ $psLines = $psLines | append (printf "New-Item -ItemType Directory -Force -Path %s | Out-Null" $name) }} {{ range $d := $dirs }} {{ $psLines = $psLines | append (printf "New-Item -ItemType Directory -Force -Path %s/%s | Out-Null" $name $d) }} {{ end }} {{ $psLines = $psLines | append (printf "Set-Location %s" $name) }} {{ range $files }} {{ $psLines = $psLines | append (printf "WriteFile '%s' @'" .path) }} {{ $psLines = $psLines | append .content }} {{ $psLines = $psLines | append "'@" }} {{ end }} {{ $psScript := delimit $psLines "\n" }} {{/* Build a tree-friendly view of the file list. - $rootFiles: files at project root (dict with "index" and "name") - $folderPaths: ordered, deduped list of folder paths (parents auto-included) - $folderFiles: map of folder path -> slice of files in that folder We then sort $folderPaths lexicographically so parents naturally come before their children when iterating. */}} {{ $rootFiles := slice }} {{ $folderPaths := slice }} {{ $folderFiles := dict }} {{ range $i, $f := $files }} {{ $dir := path.Dir $f.path }} {{ $entry := dict "index" $i "name" (path.Base $f.path) "path" $f.path "status" ($f.status | default "") }} {{ if eq $dir "." }} {{ $rootFiles = $rootFiles | append $entry }} {{ else }} {{/* Make sure every parent folder along the path is registered. */}} {{ $parts := split $dir "/" }} {{ $prefix := "" }} {{ range $part := $parts }} {{ if $prefix }} {{ $prefix = printf "%s/%s" $prefix $part }} {{ else }} {{ $prefix = $part }} {{ end }} {{ if not (in $folderPaths $prefix) }} {{ $folderPaths = $folderPaths | append $prefix }} {{ end }} {{ end }} {{ $existing := index $folderFiles $dir | default slice }} {{ $existing = $existing | append $entry }} {{ $folderFiles = merge $folderFiles (dict $dir $existing) }} {{ end }} {{ end }} {{ $folderPaths = sort $folderPaths }}
{{/* Window title bar */}}
{{ $name }}
{{/* Primary view toggle: Files | Scaffold script */}}
{{/* Files view: sidebar + content (fixed height with internal scroll) */}}
{{/* Sidebar */}} {{/* Content pane. The outer `main` is the positioning context for the copy button and stays fixed; the inner div is the scroll container so content scrolls independently of the button. The chroma `.highlight` wrapper's own overflow-x is disabled so the scroll container owns both axes and scrollbars sit at the window edges. */}}
{{/* Per-file copy button. Matches the codeblock copy style: icon-only, hover-revealed, swaps to a check icon for two seconds on copy. */}}
{{ range $i, $f := $files }} {{ $opts := "" }} {{ with $f.hl_lines }} {{ $opts = printf "hl_lines=%s" . }} {{ end }}
{{ (transform.Highlight $f.content $f.lang $opts) | safeHTML }}
{{ end }}
{{/* Scaffold script view, with Bash | PowerShell secondary toggle (fixed height with internal scroll) */}}
{{/* Yellow callout: warning + shell selector */}}
{{ partialCached "icon" "exclamation-triangle" "exclamation-triangle" }} Overwrites existing files with the same names. Run from the parent of your project directory.
{{/* Code area. Outer div is the positioning context for the copy button and stays fixed; inner div is the scroll container. */}}
{{ (transform.Highlight $bashScript "bash" "") | safeHTML }}
{{ (transform.Highlight $psScript "powershell" "") | safeHTML }}