#!/bin/sh# SPDX-License-Identifier: ISC# Mirror every man/*.[1-9] page into ../docs/ as markdown, via mandoc's own# native "-T markdown" mode (mdoc -> markdown, not the other direction --# see the design discussion this came out of: pandoc's markdown -> man# writer emits font escapes mandoc doesn't implement and can't be linted# by check-docs.sh, so mdoc stays the one source of truth and this is# purely a generated, read-only view of it).## mandoc's own docs call -T markdown lossy ("a very weak markup language,# so all semantic markup is lost"), and two specific things it drops are# ugly enough on GitHub to fix with a small sed pass, kept to real# CommonMark syntax (not HTML -- an earlier version of this script# switched to -T html -O fragment wrapped in a .md extension, which# looked better on GitHub specifically but produces something that is# not actually markdown at all; any real markdown renderer/linter/# converter run over it would either choke or dump raw tags as literal# text. reverted: better to keep these as genuine, portable markdown with# two small known cosmetic gaps than something that only works in one# specific renderer's HTML-passthrough leniency):## - .Xr cross-references render as inert "name(section)" text, since# mandoc has no way to know these pages are about to sit next to each# other as sibling files. rewritten below into a real markdown link# for any Xr target that matches another page in this same sync run;# a reference to something outside this project (errno(2), fnmatch(3),# etc) has nothing to link to and is correctly left as plain text.# - .Bl -tag list item bodies render as "> "-prefixed blockquotes (a# nested list, e.g. providers.*.api_key inside clm-config(5), comes# out doubly/triply nested as "> > "/"> > > "), which is a reasonable# one-to-one mapping in isolation but reads badly on GitHub for a# multi-paragraph body (nested-looking, not a real quotation). Since# nothing in these pages is an actual quotation, every leading run of# "> " is stripped from every such line, turning it back into a plain# paragraph regardless of nesting depth.set -eMANDOC="${1:?usage: docs-sync.sh MANDOC MANDIR DOCSDIR}"MANDIR="${2:?usage: docs-sync.sh MANDOC MANDIR DOCSDIR}"DOCSDIR="${3:?usage: docs-sync.sh MANDOC MANDIR DOCSDIR}"mkdir -p "$DOCSDIR"# Build the sed program: one Xr-linking substitution per page about to be# generated in this run, plus the blanket "> " stripping rule.sedprog=$(mktemp)trap 'rm -f "$sedprog"' EXIT: > "$sedprog"for page in "$MANDIR"/*.[1-9]; do [ -f "$page" ] || continue base=$(basename "$page") name=${base%.*} section=${base##*.} # Escape sed/BRE metacharacters in the page name (clm-tool's '-' is # harmless as-is, but keep this robust for any future page name). esc=$(printf '%s' "$name" | sed 's/[.[\*^$/]/\\&/g') printf 's|%s(%s)|[%s(%s)](%s.md)|g\n' \ "$esc" "$section" "$name" "$section" "$name" >> "$sedprog" # mandoc's markdown writer backslash-escapes every underscore in # running text (markdown's own italic-delimiter character), so # clm_agent(3) is literally "clm\_agent(3)" in the generated file. # Only add this second substitution when the name actually has an # underscore -- otherwise it's identical to the rule just above and # would double-substitute already-linked text (e.g. clm(1) has no # underscore, so without this guard both rules fire on the same # span, producing "[[clm(1)](clm.md)](clm.md)"). case "$name" in *_*) escu=$(printf '%s' "$esc" | sed 's/_/\\\\_/g') printf 's|%s(%s)|[%s(%s)](%s.md)|g\n' \ "$escu" "$section" "$name" "$section" "$name" >> "$sedprog" ;; esacdone# Strip every leading "> " (mandoc's rendering of a .Bl -tag item body --# nested lists produce "> > ", "> > > ", etc, so repeat the substitution# on the same line rather than stripping only the outermost level).# Nothing in these pages is a real blockquote.printf 's|^\(> \)*||\n' >> "$sedprog"for page in "$MANDIR"/*.[1-9]; do [ -f "$page" ] || continue base=$(basename "$page") name=${base%.*} out="$DOCSDIR/$name.md" # -I os=clm: pin the .Os trailer instead of letting it default to # whatever uname()/os-release the machine running this happens to # report (Debian here, OpenBSD elsewhere, etc) -- otherwise every # re-sync from a different machine would diff on nothing but that, # with no real content change. "$MANDOC" -I os=clm -T markdown "$page" | sed -f "$sedprog" > "$out" echo "wrote $out"done
#!/bin/sh
# SPDX-License-Identifier: ISC
# Mirror every man/*.[1-9] page into ../docs/ as markdown, via mandoc's own
# native "-T markdown" mode (mdoc -> markdown, not the other direction --
# see the design discussion this came out of: pandoc's markdown -> man
# writer emits font escapes mandoc doesn't implement and can't be linted
# by check-docs.sh, so mdoc stays the one source of truth and this is
# purely a generated, read-only view of it).
#
# mandoc's own docs call -T markdown lossy ("a very weak markup language,
# so all semantic markup is lost"), and two specific things it drops are
# ugly enough on GitHub to fix with a small sed pass, kept to real
# CommonMark syntax (not HTML -- an earlier version of this script
# switched to -T html -O fragment wrapped in a .md extension, which
# looked better on GitHub specifically but produces something that is
# not actually markdown at all; any real markdown renderer/linter/
# converter run over it would either choke or dump raw tags as literal
# text. reverted: better to keep these as genuine, portable markdown with
# two small known cosmetic gaps than something that only works in one
# specific renderer's HTML-passthrough leniency):
#
# - .Xr cross-references render as inert "name(section)" text, since
# mandoc has no way to know these pages are about to sit next to each
# other as sibling files. rewritten below into a real markdown link
# for any Xr target that matches another page in this same sync run;
# a reference to something outside this project (errno(2), fnmatch(3),
# etc) has nothing to link to and is correctly left as plain text.
# - .Bl -tag list item bodies render as "> "-prefixed blockquotes (a
# nested list, e.g. providers.*.api_key inside clm-config(5), comes
# out doubly/triply nested as "> > "/"> > > "), which is a reasonable
# one-to-one mapping in isolation but reads badly on GitHub for a
# multi-paragraph body (nested-looking, not a real quotation). Since
# nothing in these pages is an actual quotation, every leading run of
# "> " is stripped from every such line, turning it back into a plain
# paragraph regardless of nesting depth.
set -e
MANDOC="${1:?usage: docs-sync.sh MANDOC MANDIR DOCSDIR}"
MANDIR="${2:?usage: docs-sync.sh MANDOC MANDIR DOCSDIR}"
DOCSDIR="${3:?usage: docs-sync.sh MANDOC MANDIR DOCSDIR}"
mkdir -p "$DOCSDIR"
# Build the sed program: one Xr-linking substitution per page about to be
# generated in this run, plus the blanket "> " stripping rule.
sedprog=$(mktemp)
trap 'rm -f "$sedprog"' EXIT
: > "$sedprog"
for page in "$MANDIR"/*.[1-9]; do
[ -f "$page" ] || continue
base=$(basename "$page")
name=${base%.*}
section=${base##*.}
# Escape sed/BRE metacharacters in the page name (clm-tool's '-' is
# harmless as-is, but keep this robust for any future page name).
esc=$(printf '%s' "$name" | sed 's/[.[\*^$/]/\\&/g')
printf 's|%s(%s)|[%s(%s)](%s.md)|g\n' \
"$esc" "$section" "$name" "$section" "$name" >> "$sedprog"
# mandoc's markdown writer backslash-escapes every underscore in
# running text (markdown's own italic-delimiter character), so
# clm_agent(3) is literally "clm\_agent(3)" in the generated file.
# Only add this second substitution when the name actually has an
# underscore -- otherwise it's identical to the rule just above and
# would double-substitute already-linked text (e.g. clm(1) has no
# underscore, so without this guard both rules fire on the same
# span, producing "[[clm(1)](clm.md)](clm.md)").
case "$name" in
*_*)
escu=$(printf '%s' "$esc" | sed 's/_/\\\\_/g')
printf 's|%s(%s)|[%s(%s)](%s.md)|g\n' \
"$escu" "$section" "$name" "$section" "$name" >> "$sedprog"
;;
esac
done
# Strip every leading "> " (mandoc's rendering of a .Bl -tag item body --
# nested lists produce "> > ", "> > > ", etc, so repeat the substitution
# on the same line rather than stripping only the outermost level).
# Nothing in these pages is a real blockquote.
printf 's|^\(> \)*||\n' >> "$sedprog"
for page in "$MANDIR"/*.[1-9]; do
[ -f "$page" ] || continue
base=$(basename "$page")
name=${base%.*}
out="$DOCSDIR/$name.md"
# -I os=clm: pin the .Os trailer instead of letting it default to
# whatever uname()/os-release the machine running this happens to
# report (Debian here, OpenBSD elsewhere, etc) -- otherwise every
# re-sync from a different machine would diff on nothing but that,
# with no real content change.
"$MANDOC" -I os=clm -T markdown "$page" | sed -f "$sedprog" > "$out"
echo "wrote $out"
done