feat(arty): generate full Markdown doc in notes command

- New generate_notes_md(): builds title, description blockquote,
  dependencies table, per-script fenced blocks, and details section
  from the entire arty.yml using existing yq helpers
- show_notes() now accepts --raw to print raw Markdown; formatted
  mode pipes through the same glow/mdcat/python3 render pipeline
- Removes the decorative ━━━ border (clashes with full-document output)
- main() passes args[] through to show_notes for flag forwarding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 10:42:57 +02:00
co-authored by Claude Sonnet 4.6
parent 31932b956b
commit a8d2f457eb
+122 -34
View File
@@ -1005,46 +1005,138 @@ list_libs() {
echo
}
# Display notes from arty.yml with markdown rendering
show_notes() {
# Generate a comprehensive Markdown document from arty.yml
generate_notes_md() {
local config_file="${1:-$ARTY_CONFIG_FILE}"
local md=""
if [[ ! -f "$config_file" ]]; then
log_error "Config file not found: $config_file"
# Read top-level fields
local name version description author license url notes
name=$(get_yaml_field "$config_file" "name")
version=$(get_yaml_field "$config_file" "version")
description=$(get_yaml_field "$config_file" "description")
author=$(get_yaml_field "$config_file" "author")
license=$(get_yaml_field "$config_file" "license")
url=$(get_yaml_field "$config_file" "url")
notes=$(yq eval '.notes' "$config_file" 2>/dev/null)
# Null-clean
[[ "$name" == "null" || -z "$name" ]] && name="$(basename "$PWD")"
[[ "$version" == "null" ]] && version=""
[[ "$description" == "null" ]] && description=""
[[ "$author" == "null" ]] && author=""
[[ "$license" == "null" ]] && license=""
[[ "$url" == "null" ]] && url=""
[[ "$notes" == "null" ]] && notes=""
# Title
if [[ -n "$version" ]]; then
md+="# ${name} · v${version}"$'\n\n'
else
md+="# ${name}"$'\n\n'
fi
# Description as blockquote
if [[ -n "$description" ]]; then
while IFS= read -r line; do
md+="> ${line}"$'\n'
done <<< "$description"
md+=$'\n'
md+="---"$'\n\n'
fi
# Overview (.notes field)
if [[ -n "$notes" ]]; then
md+="## Overview"$'\n\n'
md+="${notes}"$'\n\n'
md+="---"$'\n\n'
fi
# Dependencies table
local ref_count
ref_count=$(yq eval '.references | length' "$config_file" 2>/dev/null)
if [[ "$ref_count" =~ ^[0-9]+$ ]] && [[ "$ref_count" -gt 0 ]]; then
md+="## Dependencies"$'\n\n'
md+="| Package | Location | Ref |"$'\n'
md+="|---------|----------|-----|"$'\n'
for ((i=0; i<ref_count; i++)); do
local ref_data ref_url ref_into ref_ref pkg_name _rest _rest2
ref_data=$(parse_reference "$config_file" "$i")
ref_url="${ref_data%%|*}"
_rest="${ref_data#*|}"
ref_into="${_rest%%|*}"
_rest2="${_rest#*|}"
ref_ref="${_rest2%%|*}"
pkg_name=$(get_lib_name "$ref_url")
[[ -z "$ref_into" ]] && ref_into=".arty/libs/${pkg_name}"
[[ -z "$ref_ref" ]] && ref_ref="—"
md+="| \`${pkg_name}\` | \`${ref_into}\` | ${ref_ref} |"$'\n'
done
md+=$'\n'
md+="---"$'\n\n'
fi
# Scripts
local script_names
script_names=$(list_yaml_scripts "$config_file" 2>/dev/null)
if [[ -n "$script_names" ]]; then
md+="## Scripts"$'\n\n'
while IFS= read -r script_name; do
[[ -z "$script_name" ]] && continue
local cmd
cmd=$(get_yaml_script "$config_file" "$script_name")
[[ "$cmd" == "null" || -z "$cmd" ]] && continue
md+="### \`${script_name}\`"$'\n\n'
md+="\`\`\`sh"$'\n'
md+="${cmd}"$'\n'
md+="\`\`\`"$'\n\n'
done <<< "$script_names"
md+="---"$'\n\n'
fi
# Details
local has_details=0
[[ -n "$author" ]] && has_details=1
[[ -n "$license" ]] && has_details=1
[[ -n "$url" ]] && has_details=1
if [[ "$has_details" -eq 1 ]]; then
md+="## Details"$'\n\n'
[[ -n "$author" ]] && md+="- **Author**: ${author}"$'\n'
[[ -n "$license" ]] && md+="- **License**: ${license}"$'\n'
[[ -n "$url" ]] && md+="- **URL**: [${url}](${url})"$'\n'
fi
printf '%s' "$md"
}
# Display notes from arty.yml — generated from the full config
show_notes() {
local raw_mode=0
for arg in "$@"; do [[ "$arg" == "--raw" ]] && raw_mode=1; done
if [[ ! -f "$ARTY_CONFIG_FILE" ]]; then
log_error "Config file not found: $ARTY_CONFIG_FILE"
return 1
fi
# Get notes field from YAML
local notes=$(yq eval '.notes' "$config_file" 2>/dev/null)
local md
md=$(generate_notes_md "$ARTY_CONFIG_FILE")
if [[ -z "$notes" ]] || [[ "$notes" == "null" ]]; then
log_info "No notes found in $config_file"
log_info "Add a 'notes' field to your arty.yml to display project notes"
if [[ "$raw_mode" -eq 1 ]]; then
printf '%s\n' "$md"
return 0
fi
# Get project name for header
local project_name=$(get_yaml_field "$config_file" "name")
[[ "$project_name" == "null" ]] && project_name="$(basename "$PWD")"
echo
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BOLD}${GREEN} Notes: ${project_name}${NC}"
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo
# Try to render markdown with available tools
if command -v glow &>/dev/null; then
# Use glow if available (best option)
echo "$notes" | glow -
printf '%s\n' "$md" | glow -
elif command -v mdcat &>/dev/null; then
# Use mdcat if available (good alternative)
echo "$notes" | mdcat
printf '%s\n' "$md" | mdcat
elif command -v python3 &>/dev/null; then
# Fallback to Python markdown rendering - create temp file to avoid quoting issues
local temp_notes=$(mktemp)
echo "$notes" > "$temp_notes"
python3 - "$temp_notes" <<'EOPY' 2>/dev/null || echo "$notes"
local tmp
tmp=$(mktemp)
printf '%s\n' "$md" > "$tmp"
python3 - "$tmp" <<'EOPY' 2>/dev/null || printf '%s\n' "$md"
import sys
import re
@@ -1102,14 +1194,10 @@ text = re.sub(r'^(\d+)\. (.+)$', r' \1. \2', text, flags=re.MULTILINE)
print(text)
EOPY
rm -f "$temp_notes"
rm -f "$tmp"
else
# Absolute fallback: just print the raw text
echo "$notes"
printf '%s\n' "$md"
fi
echo
echo -e "${BOLD}${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo
}
@@ -1537,7 +1625,7 @@ main() {
list_libs
;;
notes)
show_notes
show_notes "${args[@]}"
;;
scripts)
list_scripts