|
| 1 | +#!/bin/bash |
| 2 | +# Build the self-contained PDF edition of The Unmoored Self. |
| 3 | +# Requires: pandoc, Google Chrome. Run from the repo root: |
| 4 | +# bash tools/build-pdf.sh |
| 5 | +set -euo pipefail |
| 6 | + |
| 7 | +mkdir -p build |
| 8 | + |
| 9 | +python3 - <<'EOF' |
| 10 | +import re, os |
| 11 | +
|
| 12 | +SITE = "https://pzwang.github.io/unmoored-self/" |
| 13 | +order = [ |
| 14 | + ("the-unmoored-self.md", None), |
| 15 | + ("briefing/00-overview.md", "PART TWO — THE BRIEFING"), |
| 16 | + ("briefing/01-the-collapse-of-distance.md", None), |
| 17 | + ("briefing/02-the-self-without-a-floor.md", None), |
| 18 | + ("briefing/03-the-simulacrum-engine.md", None), |
| 19 | + ("briefing/04-interventions-and-their-limits.md", None), |
| 20 | + ("briefing/05-the-choice-trap.md", None), |
| 21 | + ("briefing/06-the-convergence.md", None), |
| 22 | + ("briefing/07-design-implications.md", None), |
| 23 | + ("briefing/transcript-audio-minibook.md", "PART THREE — THE AUDIO MINI-BOOK"), |
| 24 | + ("references/README.md", "APPENDIX — SOURCES"), |
| 25 | +] |
| 26 | +
|
| 27 | +def rewrite_links(text, srcdir): |
| 28 | + def repl(m): |
| 29 | + label, link = m.group(1), m.group(2) |
| 30 | + if link.startswith(("http", "mailto:", "#")): |
| 31 | + return m.group(0) |
| 32 | + path = os.path.normpath(os.path.join(srcdir, link.split("#")[0])) |
| 33 | + frag = "#" + link.split("#")[1] if "#" in link else "" |
| 34 | + if path.endswith(".md"): |
| 35 | + path = path[:-3] + ".html" |
| 36 | + if path in ("index.html",): |
| 37 | + path = "" |
| 38 | + return f"[{label}]({SITE}{path.replace(' ', '%20')}{frag})" |
| 39 | + return re.sub(r"\[([^\]]*)\]\(([^)]+)\)", repl, text) |
| 40 | +
|
| 41 | +parts = [] |
| 42 | +for f, part in order: |
| 43 | + text = open(f).read() |
| 44 | + text = rewrite_links(text, os.path.dirname(f)) |
| 45 | + if part: |
| 46 | + parts.append(f'\n\n<div class="part-divider">{part}</div>\n\n') |
| 47 | + parts.append('\n\n<div class="chapter"></div>\n\n' + text) |
| 48 | +
|
| 49 | +front = """<div class="titlepage"> |
| 50 | +<h1 class="book-title">The Unmoored Self</h1> |
| 51 | +<p class="book-subtitle">Media, Meaning, and the Crisis of Modern Communal Life</p> |
| 52 | +<p class="book-author">Peter Wang</p> |
| 53 | +<p class="book-note">The essay, the briefing suite for builders of social software, |
| 54 | +and the audio mini-book — self-contained edition, 2026.<br> |
| 55 | +Live version: <a href="https://pzwang.github.io/unmoored-self/">pzwang.github.io/unmoored-self</a></p> |
| 56 | +</div> |
| 57 | +""" |
| 58 | +open("build/combined.md", "w").write(front + "".join(parts)) |
| 59 | +print("combined:", len("".join(parts).split()), "words") |
| 60 | +EOF |
| 61 | + |
| 62 | +cp tools/pdf.css build/pdf.css |
| 63 | +pandoc build/combined.md -f gfm -t html5 -s --css=pdf.css \ |
| 64 | + --metadata title="The Unmoored Self" -o build/unmoored-self.html |
| 65 | + |
| 66 | +"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ |
| 67 | + --headless --disable-gpu --no-pdf-header-footer \ |
| 68 | + --print-to-pdf="$PWD/unmoored-self.pdf" \ |
| 69 | + "file://$PWD/build/unmoored-self.html" |
| 70 | + |
| 71 | +ls -lh unmoored-self.pdf |
0 commit comments