container-superposition 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,50 @@ deduplicate_packages() {
14
14
  echo "$packages" | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//'
15
15
  }
16
16
 
17
+ resolve_package_token() {
18
+ local manager="$1"
19
+ local token="$2"
20
+ local IFS='|'
21
+ read -r -a candidates <<< "$token"
22
+
23
+ for candidate in "${candidates[@]}"; do
24
+ if [ -z "$candidate" ]; then
25
+ continue
26
+ fi
27
+
28
+ if [ "$manager" = "apt" ]; then
29
+ if apt-cache show "$candidate" >/dev/null 2>&1; then
30
+ echo "$candidate"
31
+ return 0
32
+ fi
33
+ elif [ "$manager" = "apk" ]; then
34
+ if apk search -x "$candidate" >/dev/null 2>&1; then
35
+ echo "$candidate"
36
+ return 0
37
+ fi
38
+ fi
39
+ done
40
+
41
+ return 1
42
+ }
43
+
44
+ resolve_package_list() {
45
+ local manager="$1"
46
+ local packages="$2"
47
+ local resolved=()
48
+
49
+ for token in $packages; do
50
+ local selected=""
51
+ if ! selected=$(resolve_package_token "$manager" "$token"); then
52
+ echo "❌ No package candidate found for \"$token\" using $manager" >&2
53
+ exit 1
54
+ fi
55
+ resolved+=("$selected")
56
+ done
57
+
58
+ deduplicate_packages "${resolved[*]}"
59
+ }
60
+
17
61
  # Exit early if no packages specified
18
62
  if [ -z "$APT_PACKAGES" ] && [ -z "$APK_PACKAGES" ]; then
19
63
  echo "⚠️ No packages specified for installation"
@@ -26,9 +70,8 @@ echo "📦 Installing cross-distro packages..."
26
70
  if command -v apk > /dev/null 2>&1; then
27
71
  # Alpine Linux (apk)
28
72
  if [ -n "$APK_PACKAGES" ]; then
29
- # Deduplicate package list
30
- APK_PACKAGES=$(deduplicate_packages "$APK_PACKAGES")
31
-
73
+ APK_PACKAGES=$(resolve_package_list "apk" "$APK_PACKAGES")
74
+
32
75
  echo " Detected: Alpine Linux (apk)"
33
76
  echo " Installing: $APK_PACKAGES"
34
77
  apk add --no-cache $APK_PACKAGES
@@ -39,12 +82,11 @@ if command -v apk > /dev/null 2>&1; then
39
82
  elif command -v apt-get > /dev/null 2>&1; then
40
83
  # Debian/Ubuntu (apt)
41
84
  if [ -n "$APT_PACKAGES" ]; then
42
- # Deduplicate package list
43
- APT_PACKAGES=$(deduplicate_packages "$APT_PACKAGES")
44
-
85
+ apt-get update
86
+ APT_PACKAGES=$(resolve_package_list "apt" "$APT_PACKAGES")
87
+
45
88
  echo " Detected: Debian/Ubuntu (apt)"
46
89
  echo " Installing: $APT_PACKAGES"
47
- apt-get update
48
90
  DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $APT_PACKAGES
49
91
  apt-get clean
50
92
  rm -rf /var/lib/apt/lists/*
@@ -0,0 +1,279 @@
1
+ # Pandoc PDF Overlay
2
+
3
+ Adds a complete Markdown → PDF pipeline to your devcontainer, powered by Pandoc, XeLaTeX, and optional Mermaid diagram rendering.
4
+
5
+ ## Features
6
+
7
+ - **Pandoc 3.x** — Latest release binary from GitHub (not the outdated apt version)
8
+ - **TeX Live / XeLaTeX** — Full Unicode-capable PDF engine (`texlive-xetex`, `texlive-fonts-extra`, `texlive-latex-extra`)
9
+ - **Quality fonts** — Carlito (body), JetBrains Mono (code), Noto Sans Symbols 2 (Unicode fallback) via system packages
10
+ - Uses the `cross-distro-packages` feature with fallback package names for Carlito (`fonts-carlito|fonts-crosextra-carlito`)
11
+ - **`diagram.lua`** — Lua filter from [pandoc-ext/diagram](https://github.com/pandoc-ext/diagram) for rendering code-block diagrams
12
+ - **Mermaid CLI (`mmdc`)** — Installed when the `nodejs` overlay is present; skipped gracefully otherwise
13
+ - **`~/.pandoc/pandoc.yaml`** — Ready-to-use defaults file (XeLaTeX engine, font settings, table tweaks)
14
+ - **VS Code Extensions:** Markdown All in One (`yzhang.markdown-all-in-one`), markdownlint (`DavidAnson.vscode-markdownlint`)
15
+
16
+ ## How It Works
17
+
18
+ System packages are installed through the `cross-distro-packages` feature, which handles package-manager detection and now supports fallback package names for distro variants. The setup script then downloads the official Pandoc `.deb` from GitHub releases (Pandoc 3.x is required for `diagram.lua`'s `Figure` AST element). Chromium is installed system-wide to serve as Puppeteer's browser for Mermaid headless rendering.
19
+
20
+ The pipeline:
21
+
22
+ ```text
23
+ Markdown
24
+ -> pandoc
25
+ -> diagram.lua (Lua filter, optional)
26
+ -> mmdc (Mermaid CLI, headless Chromium)
27
+ -> XeLaTeX
28
+ -> PDF
29
+ ```
30
+
31
+ Font discovery is updated with `fc-cache -fv` after installation so XeLaTeX can locate the apt-installed fonts.
32
+
33
+ ## Common Commands
34
+
35
+ ### Basic PDF export
36
+
37
+ ```bash
38
+ # Use the default pandoc.yaml
39
+ pandoc -d ~/.pandoc/pandoc.yaml document.md -o document.pdf
40
+
41
+ # Override the output font on the fly
42
+ pandoc -d ~/.pandoc/pandoc.yaml -V mainfont="DejaVu Serif" document.md -o document.pdf
43
+ ```
44
+
45
+ ### PDF with Mermaid diagrams (requires nodejs overlay)
46
+
47
+ ```bash
48
+ pandoc -d ~/.pandoc/pandoc.yaml \
49
+ --lua-filter ~/.pandoc/filters/diagram.lua \
50
+ document.md -o document.pdf
51
+ ```
52
+
53
+ ### Inspect installed fonts
54
+
55
+ ```bash
56
+ fc-list | grep -i carlito
57
+ fc-list | grep -i jetbrains
58
+ fc-list | grep -i "noto sans symbols"
59
+ ```
60
+
61
+ ### Check Pandoc version
62
+
63
+ ```bash
64
+ pandoc --version
65
+ ```
66
+
67
+ ## Mermaid Diagram Usage
68
+
69
+ Add fenced `mermaid` code blocks to your Markdown:
70
+
71
+ ````markdown
72
+ ```mermaid
73
+ graph TD
74
+ A[Start] --> B{Decision}
75
+ B -->|Yes| C[Action]
76
+ B -->|No| D[End]
77
+ ```
78
+ ````
79
+
80
+ Render with the `diagram.lua` filter:
81
+
82
+ ```bash
83
+ pandoc -d ~/.pandoc/pandoc.yaml \
84
+ --lua-filter ~/.pandoc/filters/diagram.lua \
85
+ document.md -o document.pdf
86
+ ```
87
+
88
+ The filter invokes `mmdc` for each `mermaid` block, producing a PNG that XeLaTeX embeds in the PDF. The Puppeteer configuration at `~/.config/mermaid/puppeteer-config.json` points `mmdc` at the system Chromium with `--no-sandbox`, which is required inside containers.
89
+
90
+ ## Configuration
91
+
92
+ ### Default `~/.pandoc/pandoc.yaml`
93
+
94
+ The setup script writes a defaults file with proven settings:
95
+
96
+ ```yaml
97
+ pdf-engine: xelatex
98
+
99
+ variables:
100
+ mainfont: 'Carlito'
101
+ monofont: 'JetBrains Mono'
102
+ fallbackfont: 'Noto Sans Symbols 2'
103
+ fontsize: 11pt
104
+ linestretch: 1.15
105
+ geometry:
106
+ - top=16mm
107
+ - bottom=16mm
108
+ - left=14mm
109
+ - right=14mm
110
+ header-includes:
111
+ - |
112
+ \usepackage{etoolbox}
113
+ \setlength{\tabcolsep}{3pt}
114
+ \renewcommand{\arraystretch}{1.05}
115
+ \AtBeginEnvironment{longtable}{\small}
116
+ \AtBeginEnvironment{tabular}{\small}
117
+ ```
118
+
119
+ ### Per-project override
120
+
121
+ Create a `pandoc.yaml` in your project directory to override the defaults:
122
+
123
+ ```yaml
124
+ # project/pandoc.yaml
125
+ pdf-engine: xelatex
126
+ variables:
127
+ mainfont: 'DejaVu Serif'
128
+ fontsize: 12pt
129
+ toc: true
130
+ toc-depth: 3
131
+ number-sections: true
132
+ lua-filter:
133
+ - ~/.pandoc/filters/diagram.lua
134
+ ```
135
+
136
+ Then build with:
137
+
138
+ ```bash
139
+ pandoc -d pandoc.yaml document.md -o document.pdf
140
+ ```
141
+
142
+ ### Enable TOC and section numbering
143
+
144
+ Uncomment the relevant lines in `~/.pandoc/pandoc.yaml`:
145
+
146
+ ```yaml
147
+ toc: true
148
+ toc-depth: 3
149
+ number-sections: true
150
+ ```
151
+
152
+ ### Enable Mermaid rendering by default
153
+
154
+ Uncomment in `~/.pandoc/pandoc.yaml`:
155
+
156
+ ```yaml
157
+ lua-filter:
158
+ - ~/.pandoc/filters/diagram.lua
159
+ ```
160
+
161
+ ## Unicode and Emoji
162
+
163
+ XeLaTeX handles Unicode well with the Noto and Carlito fonts, but emoji (🎉 🚀) require a colour emoji font (e.g. `fonts-noto-color-emoji`) which is not installed by default due to size. For documents with emoji, either:
164
+
165
+ 1. Replace emoji with text equivalents before generating the PDF:
166
+
167
+ ```bash
168
+ sed 's/🎉/[celebration]/g; s/🚀/[rocket]/g' doc.md | pandoc -d ~/.pandoc/pandoc.yaml -o doc.pdf
169
+ ```
170
+
171
+ 2. Install `fonts-noto-color-emoji` and add `\setmainfont{Noto Color Emoji}` for the emoji font fallback in your `header-includes`.
172
+
173
+ ## Use Cases
174
+
175
+ - **Architecture documentation** — Architecture Decision Records (ADRs), system design docs
176
+ - **API specifications** — OpenAPI-style documentation with code samples
177
+ - **Technical reports** — Multi-section documents with tables and diagrams
178
+ - **README to PDF** — Convert project READMEs to distributable PDF format
179
+
180
+ **Integrates well with:**
181
+
182
+ - `nodejs` overlay — Enables Mermaid CLI for diagram rendering
183
+ - `git-helpers` overlay — Commit generated PDFs alongside source Markdown
184
+ - `modern-cli-tools` overlay — Use `bat` to preview Markdown, `rg` to search documents
185
+
186
+ ## Troubleshooting
187
+
188
+ ### `xelatex: command not found`
189
+
190
+ TeX Live was not installed correctly. Re-run the setup script:
191
+
192
+ ```bash
193
+ bash .devcontainer/scripts/setup-pandoc.sh
194
+ ```
195
+
196
+ ### Missing glyph warnings / blank characters in PDF
197
+
198
+ The font does not include that glyph. For common Unicode symbols, Noto Sans Symbols 2 covers most cases. Verify it is installed:
199
+
200
+ ```bash
201
+ fc-list | grep -i "noto sans symbols 2"
202
+ ```
203
+
204
+ If not found, rebuild the font cache:
205
+
206
+ ```bash
207
+ sudo fc-cache -fv
208
+ ```
209
+
210
+ ### Wide tables overflow page margins
211
+
212
+ The `header-includes` in `pandoc.yaml` applies `\small` inside `longtable` and `tabular` environments. For very wide tables, also add `\tiny` or use column width constraints in your Markdown:
213
+
214
+ ```markdown
215
+ | Col 1 | Col 2 | Col 3 |
216
+ | :---- | :---- | :---- |
217
+ | data | data | data |
218
+ ```
219
+
220
+ ### Mermaid: Chromium crashes or `--no-sandbox` error
221
+
222
+ The Puppeteer config at `~/.config/mermaid/puppeteer-config.json` must set `--no-sandbox`:
223
+
224
+ ```json
225
+ {
226
+ "executablePath": "/usr/bin/chromium",
227
+ "args": ["--no-sandbox", "--disable-setuid-sandbox"]
228
+ }
229
+ ```
230
+
231
+ Verify the file exists and contains the correct content:
232
+
233
+ ```bash
234
+ cat ~/.config/mermaid/puppeteer-config.json
235
+ ```
236
+
237
+ ### `mmdc` not found
238
+
239
+ The `nodejs` overlay must be selected to install Mermaid CLI. Check if Node.js is available:
240
+
241
+ ```bash
242
+ node --version
243
+ npm --version
244
+ mmdc --version
245
+ ```
246
+
247
+ If Node.js is present but `mmdc` is missing, install it manually:
248
+
249
+ ```bash
250
+ npm install -g @mermaid-js/mermaid-cli
251
+ ```
252
+
253
+ ### Upgrading Pandoc
254
+
255
+ To upgrade to a newer Pandoc release, update `PANDOC_VERSION` in `setup.sh` and re-run it:
256
+
257
+ ```bash
258
+ PANDOC_VERSION=3.7.0 # update as needed
259
+ ARCH=$(dpkg --print-architecture)
260
+ PANDOC_DEB="pandoc-${PANDOC_VERSION}-1-${ARCH}.deb"
261
+ curl -fsSL "https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/${PANDOC_DEB}" \
262
+ -o "/tmp/${PANDOC_DEB}"
263
+ sudo dpkg -i "/tmp/${PANDOC_DEB}"
264
+ rm "/tmp/${PANDOC_DEB}"
265
+ ```
266
+
267
+ ## References
268
+
269
+ - [Pandoc releases](https://github.com/jgm/pandoc/releases)
270
+ - [pandoc-ext/diagram Lua filter](https://github.com/pandoc-ext/diagram)
271
+ - [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli)
272
+ - [Puppeteer in containers](https://pptr.dev/troubleshooting#running-puppeteer-in-docker)
273
+ - [TeX Live packages](https://packages.debian.org/search?keywords=texlive)
274
+
275
+ **Related Overlays:**
276
+
277
+ - `nodejs` — Required for Mermaid diagram rendering via `mmdc`
278
+ - `git-helpers` — Secure Git operations for committing generated docs
279
+ - `modern-cli-tools` — Productivity tools for Markdown authoring workflows
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
3
+ "features": {
4
+ "./features/cross-distro-packages": {
5
+ "apt": "texlive-xetex texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra texlive-lang-european fonts-carlito|fonts-crosextra-carlito fonts-noto fonts-noto-extra fonts-noto-mono fonts-jetbrains-mono fontconfig perl chromium",
6
+ "apk": "fontconfig perl chromium"
7
+ }
8
+ },
9
+ "customizations": {
10
+ "vscode": {
11
+ "extensions": ["yzhang.markdown-all-in-one", "DavidAnson.vscode-markdownlint"]
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,19 @@
1
+ id: pandoc
2
+ name: Pandoc PDF
3
+ description: Pandoc with XeLaTeX, Mermaid diagrams, and quality fonts for Markdown-to-PDF export
4
+ category: dev
5
+ supports: []
6
+ requires: []
7
+ suggests:
8
+ - nodejs
9
+ conflicts: []
10
+ tags:
11
+ - dev
12
+ - pandoc
13
+ - pdf
14
+ - latex
15
+ - markdown
16
+ - docs
17
+ - mermaid
18
+ ports: []
19
+ order: 25
@@ -0,0 +1,94 @@
1
+ #!/bin/bash
2
+ # pandoc overlay setup — Markdown -> PDF pipeline
3
+
4
+ set -e
5
+
6
+ echo "📦 Refreshing font cache..."
7
+ sudo fc-cache -fv
8
+
9
+ echo "📦 Installing Pandoc (latest release)..."
10
+ PANDOC_VERSION="3.6.4"
11
+
12
+ if command -v apt-get > /dev/null 2>&1; then
13
+ # Debian/Ubuntu — install official .deb from GitHub releases
14
+ ARCH=$(dpkg --print-architecture)
15
+ PANDOC_DEB="pandoc-${PANDOC_VERSION}-1-${ARCH}.deb"
16
+ curl -fsSL "https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/${PANDOC_DEB}" \
17
+ -o "/tmp/${PANDOC_DEB}"
18
+ sudo dpkg -i "/tmp/${PANDOC_DEB}"
19
+ rm "/tmp/${PANDOC_DEB}"
20
+ elif command -v apk > /dev/null 2>&1; then
21
+ # Alpine Linux — install via apk (version may differ from pinned release)
22
+ echo "⚠ Alpine detected: installing pandoc via apk (version may differ from ${PANDOC_VERSION})"
23
+ apk add --no-cache pandoc
24
+ else
25
+ echo "❌ Unsupported distro: neither apt-get nor apk found. Cannot install Pandoc."
26
+ exit 1
27
+ fi
28
+
29
+ echo "✓ pandoc $(pandoc --version | head -1)"
30
+
31
+ echo "📦 Installing diagram.lua Lua filter..."
32
+ mkdir -p "$HOME/.pandoc/filters"
33
+ curl -fsSL \
34
+ "https://raw.githubusercontent.com/pandoc-ext/diagram/main/_extensions/diagram/diagram.lua" \
35
+ -o "$HOME/.pandoc/filters/diagram.lua"
36
+
37
+ echo "📦 Installing Mermaid CLI (requires Node.js)..."
38
+ if command -v npm &>/dev/null; then
39
+ npm install -g @mermaid-js/mermaid-cli
40
+ # Point mmdc at the system Chromium (avoids Puppeteer downloading its own)
41
+ mkdir -p "$HOME/.config/mermaid"
42
+ cat > "$HOME/.config/mermaid/puppeteer-config.json" <<'EOF'
43
+ {
44
+ "executablePath": "/usr/bin/chromium",
45
+ "args": ["--no-sandbox", "--disable-setuid-sandbox"]
46
+ }
47
+ EOF
48
+ if command -v mmdc >/dev/null 2>&1; then
49
+ echo "✓ Mermaid CLI installed: $(command -v mmdc)"
50
+ else
51
+ echo "⚠ Mermaid CLI install completed but mmdc is not on PATH yet"
52
+ fi
53
+ else
54
+ echo "⚠ Node.js not found — Mermaid CLI skipped. Add the nodejs overlay for diagram support."
55
+ fi
56
+
57
+ echo "📦 Writing default pandoc.yaml..."
58
+ mkdir -p "$HOME/.pandoc"
59
+ cat > "$HOME/.pandoc/pandoc.yaml" <<'EOF'
60
+ pdf-engine: xelatex
61
+
62
+ variables:
63
+ mainfont: "Carlito"
64
+ monofont: "JetBrains Mono"
65
+ fallbackfont: "Noto Sans Symbols 2"
66
+ fontsize: 11pt
67
+ linestretch: 1.15
68
+ geometry:
69
+ - top=16mm
70
+ - bottom=16mm
71
+ - left=14mm
72
+ - right=14mm
73
+ header-includes:
74
+ - |
75
+ \usepackage{etoolbox}
76
+ \setlength{\tabcolsep}{3pt}
77
+ \renewcommand{\arraystretch}{1.05}
78
+ \AtBeginEnvironment{longtable}{\small}
79
+ \AtBeginEnvironment{tabular}{\small}
80
+
81
+ # Uncomment to enable TOC and section numbering:
82
+ # toc: true
83
+ # toc-depth: 3
84
+ # number-sections: true
85
+
86
+ # Uncomment to enable Mermaid/diagram rendering (requires nodejs overlay):
87
+ # lua-filter:
88
+ # - ~/.pandoc/filters/diagram.lua
89
+ EOF
90
+
91
+ echo ""
92
+ echo "✓ pandoc overlay setup complete"
93
+ echo "ℹ️ Build a PDF: pandoc -d ~/.pandoc/pandoc.yaml doc.md -o doc.pdf"
94
+ echo "ℹ️ With Mermaid: pandoc -d ~/.pandoc/pandoc.yaml --lua-filter ~/.pandoc/filters/diagram.lua doc.md -o doc.pdf"
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+ set -e
3
+ command -v pandoc || { echo "✗ pandoc not found"; exit 1; }
4
+ command -v xelatex || { echo "✗ xelatex not found"; exit 1; }
5
+ [ -f "$HOME/.pandoc/filters/diagram.lua" ] || { echo "✗ diagram.lua not found"; exit 1; }
6
+ [ -f "$HOME/.pandoc/pandoc.yaml" ] || { echo "✗ pandoc.yaml not found"; exit 1; }
7
+
8
+ # Smoke test: render a trivial PDF
9
+ echo "# Test" | pandoc --pdf-engine=xelatex -o /tmp/pandoc-verify-test.pdf && \
10
+ echo "✓ pandoc PDF smoke test passed" || { echo "✗ pandoc PDF render failed"; exit 1; }
11
+
12
+ rm -f /tmp/pandoc-verify-test.pdf
13
+ echo "✓ pandoc overlay: OK"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "container-superposition",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Solution-ready devcontainer templates and features with guided initialization",
5
5
  "type": "module",
6
6
  "main": "dist/scripts/init.js",