diff --git a/Makefile b/Makefile
index bbd9fc6..807088d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,99 +1,197 @@
-F=thinkjava2
+# ThinkJava2 Makefile
+# Build system for the ThinkJava2 textbook project
-all:
- pdflatex $(F).tex
- pdflatex $(F).tex
- pdflatex $(F).tex
+# =============================================================================
+# VARIABLES
+# =============================================================================
-clean:
- rm -f comment.cut $(F).aux $(F).idx $(F).ilg $(F).ind $(F).log $(F).out $(F).toc
+# Main project filename
+F := thinkjava2
-plastex:
- # Before running plastex, we need the current directory in PYTHONPATH
- # export PYTHONPATH=$PYTHONPATH:.
- latexpand --keep-comments $(F).tex > $(F).expand
- python2 preprocess.py $(F).expand > $(F).plastex
- plastex --renderer=DocBook --theme=book --image-resolution=300 --filename=$(F).xml $(F).plastex
- cd $(F); python2 ../postprocess.py $(F).xml > temp; mv temp $(F).xml
- cd $(F); python ../xmlsplit.py $(F).xml
+# Directories
+BUILD_DIR := build
+HEVEA_DIR := heveahtml
+TRINKET_DIR := trinkethtml
+DIST_DIR := dist
+DEST_DIR := /home/downey/public_html/greent/thinkjava7
-xxe:
- xmlcopyeditor ~/ThinkJava2/$(F)/$(F).xml &
+# Tools
+PYTHON := python
+PYTHON2 := python2
+PYTHON3 := python3
+LATEX := pdflatex
+PLASTEX := plastex
+HEVEA := hevea
+IMAGEN := imagen
+HACHA := hacha
+LATEXPAND := latexpand
+
+# =============================================================================
+# DEFAULT TARGET
+# =============================================================================
+
+.PHONY: all
+all: pdf
-lint:
- xmllint -noout $(F)/$(F).xml
+# Note: 'all' builds only PDF. Use specific targets for other formats:
+# make plastex - Build XML version
+# make hevea - Build HTML version
+# make trinket - Build Trinket HTML version
-#oreilly:
-# rsync -a $(F)/*.xml atlas/
-# rsync -a figs/*.pdf atlas/figs/
-# rsync -a figs/*.png atlas/figs/
-# rsync -a figs/*.jpg atlas/figs/
-# cd atlas; git add *.xml figs/*
-# cd atlas; git commit -m "Automated check in."
-# cd atlas; git push
+# =============================================================================
+# PDF BUILD
+# =============================================================================
-# if a bug (in ocaml?) causes "make hevea" to fail; use "make -i hevea" instead
+.PHONY: pdf
+pdf:
+ @echo "Building PDF..."
+ $(LATEX) $(F).tex
+ $(LATEX) $(F).tex
+ $(LATEX) $(F).tex
+ @echo "PDF build complete: $(F).pdf"
+
+# =============================================================================
+# XML BUILD (PLASTEX)
+# =============================================================================
+
+.PHONY: plastex
+plastex:
+ @echo "Building XML with PlasTeX..."
+ @mkdir -p $(BUILD_DIR)
+ # Before running plastex, we need the current directory in PYTHONPATH
+ # export PYTHONPATH=$PYTHONPATH:.
+ $(LATEXPAND) --keep-comments $(F).tex > $(F).expand
+ $(PYTHON2) preprocess.py $(F).expand > $(F).plastex
+ $(PLASTEX) --renderer=DocBook --theme=book --image-resolution=300 --filename=$(F).xml $(F).plastex
+ cd $(BUILD_DIR); $(PYTHON2) ../postprocess.py $(F).xml > temp && mv temp $(F).xml
+ cd $(BUILD_DIR); $(PYTHON) ../xmlsplit.py $(F).xml
+
+# =============================================================================
+# HTML BUILD (HEVEA)
+# =============================================================================
+# Note: hevea/ contains source files (htmlonly.tex, templates, scripts)
+# heveahtml/ contains generated HTML output (build artifacts)
.PHONY: hevea
hevea:
+ @echo "Building HTML with HeVeA..."
+ @rm -rf $(HEVEA_DIR)
+ @mkdir -p $(HEVEA_DIR)
cp $(F).tex $(F)_.tex
- rm -rf heveahtml
- mkdir heveahtml
- hevea -O -exec xxdate.exe -e latexonly.tex hevea/htmlonly.tex $(F)_
- hevea -O -exec xxdate.exe -e latexonly.tex hevea/htmlonly.tex $(F)_
- imagen -png -pdf $(F)_
- imagen -png -pdf $(F)_
- hacha $(F)_.html
- cp hevea/*.png heveahtml
+ $(HEVEA) -O -exec xxdate.exe -e latexonly.tex hevea/htmlonly.tex $(F)_
+ $(HEVEA) -O -exec xxdate.exe -e latexonly.tex hevea/htmlonly.tex $(F)_
+ $(IMAGEN) -png -pdf $(F)_
+ # $(IMAGEN) -png -pdf $(F)_
+ $(HACHA) $(F)_.html
+ cp hevea/*.png $(HEVEA_DIR)
cat custom.css >> $(F)_.css
- mv index.html $(F)_?*.html $(F)_*.png $(F)_.css heveahtml
- rm *motif.gif $(F)_.*
- sed -i 's/\\%/%/g' heveahtml/*.html
- sed -i 's/\\{/{/g' heveahtml/*.html
- sed -i 's/\\}/}/g' heveahtml/*.html
- sed -i 's/\\\\n/\\n/g' heveahtml/*.html
- sed -i 's/\\\\t/\\t/g' heveahtml/*.html
- python3 hevea/rename.py heveahtml
+ mv index.html $(F)_?*.html $(F)_*.png $(F)_.css $(HEVEA_DIR)
+ rm -f *motif.gif $(F)_.*
+ sed -i 's/\\%/%/g' $(HEVEA_DIR)/*.html
+ sed -i 's/\\{/{/g' $(HEVEA_DIR)/*.html
+ sed -i 's/\\}/}/g' $(HEVEA_DIR)/*.html
+ sed -i 's/\\\\n/\\n/g' $(HEVEA_DIR)/*.html
+ sed -i 's/\\\\t/\\t/g' $(HEVEA_DIR)/*.html
+ $(PYTHON3) hevea/rename.py $(HEVEA_DIR)
+
+# =============================================================================
+# TRINKET BUILD
+# =============================================================================
.PHONY: trinket
trinket:
+ @echo "Building Trinket HTML..."
+ @rm -rf $(TRINKET_DIR)
+ @mkdir -p $(TRINKET_DIR)
cp $(F).tex $(F)_.tex
- rm -rf trinkethtml
- mkdir trinkethtml
- hevea -O -exec xxdate.exe -e latexonly.tex trinket/htmlonly.tex $(F)_
- hevea -O -exec xxdate.exe -e latexonly.tex trinket/htmlonly.tex $(F)_
- imagen -png -pdf $(F)_
- imagen -png -pdf $(F)_
- hacha $(F)_.html
- cp trinket/*.css trinket/*.js trinkethtml
- mv index.html $(F)_.css $(F)_?*.html $(F)_*.png trinkethtml
- rm *motif.gif $(F)_.*
- sed -i 's/\\%/%/g' trinkethtml/*.html
- sed -i 's/\\{/{/g' trinkethtml/*.html
- sed -i 's/\\}/}/g' trinkethtml/*.html
- sed -i 's/\\\\n/\\n/g' trinkethtml/*.html
- sed -i 's/\\\\t/\\t/g' trinkethtml/*.html
-
- # perl postprocessing (woot) seems easier than escaping through Latex and Hevea
- perl -i -pe 's/\[\[\[\[\s?(\S*?)\s?\]\]\]\]/----{\1}----/g' trinkethtml/*.html
- perl -i -pe 's/\\<\/a\>//g' trinkethtml/*.html
- perl -0777 -i -pe 's/\
//' trinkethtml/*.html
-
- # produce nunjucks templates for our app
- mkdir trinkethtml/nunjucks
- python trinket/maketemplates.py
-
- # gather images for ease of uploading to CDN
- mkdir trinkethtml/img
- cp trinkethtml/*.png trinkethtml/img
-
-DEST = /home/downey/public_html/greent/thinkjava7
+ $(HEVEA) -O -exec xxdate.exe -e latexonly.tex trinket/htmlonly.tex $(F)_
+ $(HEVEA) -O -exec xxdate.exe -e latexonly.tex trinket/htmlonly.tex $(F)_
+ $(IMAGEN) -png -pdf $(F)_
+ $(IMAGEN) -png -pdf $(F)_
+ $(HACHA) $(F)_.html
+ cp trinket/*.css trinket/*.js $(TRINKET_DIR)
+ mv index.html $(F)_.css $(F)_?*.html $(F)_*.png $(TRINKET_DIR)
+ rm -f *motif.gif $(F)_.*
+ sed -i 's/\\%/%/g' $(TRINKET_DIR)/*.html
+ sed -i 's/\\{/{/g' $(TRINKET_DIR)/*.html
+ sed -i 's/\\}/}/g' $(TRINKET_DIR)/*.html
+ sed -i 's/\\\\n/\\n/g' $(TRINKET_DIR)/*.html
+ sed -i 's/\\\\t/\\t/g' $(TRINKET_DIR)/*.html
+ # Perl postprocessing for Trinket-specific formatting
+ perl -i -pe 's/\[\[\[\[\s?(\S*?)\s?\]\]\]\]/----{\1}----/g' $(TRINKET_DIR)/*.html
+ perl -i -pe 's/\\<\/a\>//g' $(TRINKET_DIR)/*.html
+ perl -0777 -i -pe 's/\
//' $(TRINKET_DIR)/*.html
+
+ # Produce Nunjucks templates for our app
+ @mkdir -p $(TRINKET_DIR)/nunjucks
+ $(PYTHON) trinket/maketemplates.py
+
+ # Gather images for ease of uploading to CDN
+ @mkdir -p $(TRINKET_DIR)/img
+ cp $(TRINKET_DIR)/*.png $(TRINKET_DIR)/img
+
+# =============================================================================
+# UTILITY TARGETS
+# =============================================================================
+
+.PHONY: clean
+clean:
+ @echo "Cleaning build artifacts..."
+ rm -f comment.cut $(F).aux $(F).idx $(F).ilg $(F).ind $(F).log $(F).out $(F).toc
+ rm -f $(F).expand $(F).plastex
+ rm -rf $(BUILD_DIR) $(HEVEA_DIR) $(TRINKET_DIR) $(DIST_DIR)
+
+.PHONY: clean-all
+clean-all: clean
+ @echo "Cleaning all generated files..."
+ rm -f $(F).pdf
+
+.PHONY: xxe
+xxe:
+ @echo "Opening XML in XML Copy Editor..."
+ xmlcopyeditor ~/ThinkJava2/$(BUILD_DIR)/$(F).xml &
+
+.PHONY: lint
+lint: $(BUILD_DIR)/$(F).xml
+ @echo "Validating XML..."
+ xmllint -noout $(BUILD_DIR)/$(F).xml
+
+# =============================================================================
+# DISTRIBUTION
+# =============================================================================
+
+.PHONY: distrib
distrib:
- rm -rf dist
- mkdir dist
- rsync -a $(F).pdf dist
- rsync -a heveahtml/ dist/html/
- rsync -a dist/* $(DEST)
- chmod -R o+r $(DEST)/*
- cd $(DEST)/..; sh back
+ @echo "Creating distribution package..."
+ rsync -a $(F).pdf $(DIST_DIR)
+ rsync -a $(HEVEA_DIR)/ $(DIST_DIR)/html/
+ rsync -a $(DIST_DIR)/* $(DEST_DIR)
+ chmod -R o+r $(DEST_DIR)/*
+ cd $(DEST_DIR)/..; sh back
+ @echo "Distribution complete: $(DEST_DIR)"
+
+$(DIST_DIR):
+ @mkdir -p $(DIST_DIR)
+
+# =============================================================================
+# HELP
+# =============================================================================
+
+.PHONY: help
+help:
+ @echo "ThinkJava2 Makefile - Available targets:"
+ @echo ""
+ @echo " all/pdf - Build PDF version (default)"
+ @echo " plastex - Build XML version using PlasTeX"
+ @echo " hevea - Build HTML version using HeVeA"
+ @echo " trinket - Build Trinket HTML version"
+ @echo " distrib - Create distribution package"
+ @echo ""
+ @echo " clean - Remove build artifacts"
+ @echo " clean-all - Remove all generated files"
+ @echo " lint - Validate XML output"
+ @echo " xxe - Open XML in XML Copy Editor"
+ @echo " help - Show this help message"
+ @echo ""
+ @echo "Note: If HeVeA fails due to OCaml bugs, use 'make -i hevea'"
diff --git a/README.md b/README.md
index 69e33f6..8467246 100644
--- a/README.md
+++ b/README.md
@@ -9,15 +9,101 @@ The illustrations were drawn using xfig (http://www.xfig.org/) and dia (https://
Compiling the LaTeX source has the effect of generating a device-independent representation of the book, which can be converted to other formats and printed.
-To compile the PDF version from source:
+## Building the Book
- pdflatex thinkjava2.tex
- pdflatex thinkjava2.tex
- pdflatex thinkjava2.tex
+### Prerequisites
+On Linux, you may need to install:
+- `texlive-latex-extra` and `texlive-fonts-recommended` for PDF generation
+- `plastex` for XML generation
-The source code includes a Makefile that automates this process. On Linux, you may need to install texlive-latex-extra and texlive-fonts-recommended.
+#### Installing HeVeA (Required for HTML generation)
+HeVeA is available through the OCaml Package Manager (opam):
-To build the HTML versions, the hevea package is required. Use the Makefile as follows:
+```bash
+# 1. Install opam if you don't have it
+# Debian/Ubuntu
+sudo apt install opam
- make hevea # static html
- make trinket # interactive
+# macOS with Homebrew
+brew install opam
+
+# 2. Initialize opam
+opam init
+
+# 3. Install hevea from opam (latest release from maintainer)
+opam install hevea
+
+# 4. Make sure opam's bin directory is in your PATH
+eval $(opam env)
+
+#### Troubleshooting: LaTeX Can't Find HeVeA Style File
+After installing HeVeA, you may see a warning that `hevea.sty` was installed but LaTeX can't find it. This is because the style file is in opam's directory. Here's how to fix it:
+
+**Solution: Add opam's LaTeX directory to TEXINPUTS**
+
+```bash
+# Add this line to your ~/.bashrc or ~/.zshrc
+export TEXINPUTS="$HOME/.opam/default/lib/hevea:$TEXINPUTS"
+
+# Then reload your shell configuration
+source ~/.bashrc # or source ~/.zshrc
+
+# Verify the file is now found
+kpsewhich hevea.sty
+```
+
+This should return the path to `hevea.sty` if the fix worked.
+
+
+
+### Build Options
+
+#### PDF Version (Default)
+```bash
+make pdf # or just 'make'
+```
+This runs `pdflatex` three times to resolve cross-references.
+
+#### HTML Versions
+```bash
+make hevea # Static HTML version
+make trinket # Interactive HTML version for Trinket platform
+```
+
+#### XML Version
+```bash
+make plastex # DocBook XML output
+```
+
+#### Other Targets
+```bash
+make clean # Remove build artifacts
+make clean-all # Remove all generated files including PDF
+make lint # Validate XML output
+make distrib # Create distribution package
+```
+
+### Manual PDF Build
+If you prefer to build manually:
+
+```bash
+pdflatex thinkjava2.tex
+pdflatex thinkjava2.tex
+pdflatex thinkjava2.tex
+```
+
+## Project Structure
+
+- **`*.tex`** - LaTeX source files for each chapter
+- **`figs/`** - Source figures (xfig, dia, PNG)
+- **`code/`** - Java source code examples
+- **`hevea/`** - HTML build configuration and templates
+- **`atlas/`** - Publishing workflow files
+- **`Makefile`** - Automated build system
+
+## Notes
+
+- The default `make` target builds only PDF for faster development cycles
+- Use specific targets for other formats when needed
+- Build artifacts are placed in separate directories (e.g., `heveahtml/`, `build/`)
+- If HeVeA fails due to OCaml bugs, use `make -i hevea`
diff --git a/ch01.tex b/ch01.tex
index 2d52b0b..f852c08 100644
--- a/ch01.tex
+++ b/ch01.tex
@@ -40,10 +40,10 @@ \section{What Is a Computer?}
\begin{figure}[!ht]
\begin{center}
%https://commons.wikimedia.org/wiki/File:Intel_80486DX2_top.jpg
-\includegraphics[height=11em]{figs/CPU.jpg}
+\includegraphics[height=11em,alt="Intel 80486DX2 processor chip"]{figs/CPU.jpg}
\hspace{2em}
%https://commons.wikimedia.org/wiki/File:Memory_module_DDRAM_20-03-2006.jpg
-\includegraphics[height=11em]{figs/RAM.jpg}
+\includegraphics[height=11em,alt="DDRAM memory module"]{figs/RAM.jpg}
\caption{Example processor and memory hardware.}
\label{fig.cpuram}
\end{center}
@@ -215,7 +215,7 @@ \section{Compiling Java Programs}
\begin{figure}[!ht]
\begin{center}
-\includegraphics{figs/interpreter.pdf}
+\includegraphics[alt="Interpreter reading and executing code line by line"]{figs/interpreter.pdf}
\caption{How interpreted languages are executed.}
\label{fig.interpreter}
\end{center}
@@ -256,7 +256,7 @@ \section{Compiling Java Programs}
\begin{figure}[!ht]
\begin{center}
-\includegraphics{figs/compiler.pdf}
+\includegraphics[alt="Java compilation process from source to bytecode"]{figs/compiler.pdf}
\caption{The process of compiling and running a Java program.}
\label{fig.compiler}
\end{center}
diff --git a/ch05.tex b/ch05.tex
index eddf7f9..d10440c 100644
--- a/ch05.tex
+++ b/ch05.tex
@@ -791,17 +791,17 @@ \section{Exercises}
\hline
\java{True || hello.length() > 0} & \\
\hline
-\java{hello.isEmpty() && yes} & \\
+\java{hello.isEmpty() \&\& yes} & \\
\hline
-\java{grade <= 100 && !false} & \\
+\java{grade <= 100 \&\& !false} & \\
\hline
\java{!yes || no} & \\
\hline
\java{grade > 75 > amount} & \\
\hline
-\java{amount <= hiVal && amount >= loVal} & \\
+\java{amount <= hiVal \&\& amount >= loVal} & \\
\hline
-\java{no && !no || yes && !yes} & \\
+\java{no \&\& !no || yes \&\& !yes} & \\
\hline
\end{tabular}
\end{center}
diff --git a/hevea/htmlonly.tex b/hevea/htmlonly.tex
index f007256..e2819cf 100644
--- a/hevea/htmlonly.tex
+++ b/hevea/htmlonly.tex
@@ -1,6 +1,12 @@
\usepackage{makeidx}
\makeindex
+% Set HeVeA conditional to true
+\newif\ifhevea \heveatrue
+
+% MathJax for better math rendering and accessibility
+\usepackage[auto]{mathjax}
+
\newcommand{\adjustpage}[1]{}
\newcommand{\clearemptydoublepage}{}
diff --git a/latexonly.tex b/latexonly.tex
index a0ceeca..2600c54 100644
--- a/latexonly.tex
+++ b/latexonly.tex
@@ -1,3 +1,7 @@
+\usepackage[T1]{fontenc}
+\usepackage{lmodern}
+\usepackage{textcomp}
+
\usepackage{geometry}
\geometry{
%paperwidth=6.0in,
@@ -86,7 +90,6 @@
\definecolor{strings}{HTML}{B20000}
% syntax highlighting in code listings
-\usepackage{textcomp}
\usepackage{listings}
\lstset{
language=java,
@@ -110,6 +113,7 @@
\lstnewenvironment{code}
{\minipage{\linewidth}}
{\endminipage}
+
\lstnewenvironment{stdout}
{\lstset{commentstyle=,keywordstyle=,stringstyle=}\minipage{\linewidth}}
{\endminipage}
diff --git a/thinkjava2.tex b/thinkjava2.tex
index 741d5c4..3f9d8d5 100644
--- a/thinkjava2.tex
+++ b/thinkjava2.tex
@@ -36,6 +36,7 @@
\newif\ifplastex
\plastexfalse
+
%%%% PLASTEX ONLY
\ifplastex
@@ -73,16 +74,24 @@
%%%% LATEX/HTML ONLY
\else
-%BEGIN LATEX
-\usepackage{comment}
-\excludecomment{htmlonly}
-\includecomment{latexonly}
-%END LATEX
+\makeatletter
+\@ifundefined{ifhevea}{\newif\ifhevea \heveafalse}{}
+\makeatother
-\input{latexonly.tex}
+\ifhevea
+ % HeVeA-specific setup
+ \typeout{DEBUG: HeVeA is running}
+\else
+ % LaTeX/PDF-only setup
+ \typeout{DEBUG: LaTeX is running}
+ \usepackage{comment}
+ \excludecomment{htmlonly}
+ \includecomment{latexonly}
+ \input{latexonly.tex}
\fi
+\fi
%%%% END OF PREAMBLE
\begin{document}