PreTeXt - 完整学习教程
PreTeXt - 完整学习教程
教程级别: 从零到一 预计学习时间: 20-30 小时 前置知识: 基本命令行操作、XML 基础语法、LaTeX 数学公式语法(推荐)
环境搭建指南
系统要求
- 操作系统: macOS 10.15+、Linux(Ubuntu 20.04+ 推荐)、Windows 10/11(WSL2 推荐)
- Python: 3.8+(PreTeXt-CLI 运行时)
- LaTeX 发行版: TeX Live 2020+(PDF 输出必需)或 MiKTeX
- 磁盘空间: 约 5 GB(含 TeX Live 完整安装)
- 网络: 首次构建需要下载 MathJax 等资源
安装步骤
步骤 1:安装 Python(如尚未安装)
# macOS(使用 Homebrew)
brew install python@3.11
# Ubuntu/Debian
sudo apt update && sudo apt install python3 python3-pip python3-venv
# 验证 Python 版本
python3 --version
# 预期输出:Python 3.11.x(或更高版本)
步骤 2:创建虚拟环境并安装 PreTeXt-CLI
# 创建项目目录
mkdir -p ~/pretext-projects && cd ~/pretext-projects
# 创建 Python 虚拟环境
python3 -m venv pretext-env
# 激活虚拟环境
# macOS/Linux:
source pretext-env/bin/activate
# Windows (WSL):
# source pretext-env/bin/activate
# 安装 PreTeXt-CLI(当前版本 v2.38.2)
pip install --upgrade pretext
步骤 3:安装 TeX Live(PDF 输出所需)
# macOS(使用 Homebrew,约 4GB)
brew install --cask mactex
# Ubuntu/Debian(完整安装)
sudo apt install texlive-full
# 最小安装(仅核心功能,约 500MB)
# macOS: brew install --cask basictex && eval "$(/usr/libexec/path_helper)"
# Ubuntu: sudo apt install texlive texlive-latex-extra texlive-fonts-recommended
验证安装
# 验证 PreTeXt-CLI 安装
pretext --version
# 预期输出:pretext, version 2.38.2(或更高版本)
# 验证 xsltproc(XSLT 转换引擎)
xsltproc --version
# 预期输出:Using libxml 209xx, libxslt 10xxx 及相关版本信息
# 验证 LaTeX 安装
pdflatex --version
# 预期输出:pdfTeX 3.x 等版本信息
# 检查 PreTeXt 可用的构建目标
pretext build --targets
# 预期输出:列出 html, latex, pdf, epub, slides 等可用目标
预期输出示例:
pretext, version 2.38.2
Using libxml 20913, libxslt 10139
pdfTeX 3.141592653-2.6-1.40.25 (TeX Live 2023)
Available targets: html, latex, pdf, epub, kindle, braille, slides, jupyter
第一部分:入门篇
1.1 PreTeXt 标记语言基础——编写第一个文档
概念讲解:
PreTeXt 是一种基于 XML 的标记语言。与 HTML 描述网页结构类似,PreTeXt 描述学术文档的语义结构——章节、定理、证明、练习等。你不需要描述"这段文字要加粗居中",而是告诉 PreTeXt "这是一个定理"(<theorem>),PreTeXt 会自动为每种输出格式(HTML、PDF、Braille)以最合适的方式呈现。
XML 的基本规则:
- 每个开始标签必须有对应的结束标签:<title>...</title>
- 标签可以嵌套但不能交叉:<p>...<em>...</em>...</p> 正确,<p>...<em>...</p>...</em> 错误
- 属性写在开始标签中:<theorem xml:id="thm-1">
- XML 区分大小写:<Theorem> 和 <theorem> 是不同的标签
代码示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 第一行是 XML 声明,每个 PreTeXt 文件都必须有 -->
<!-- <pretext> 是根元素,包裹整个文档 -->
<pretext>
<!-- <article> 表示一篇文章(短文档),<book> 表示一本书 -->
<article xml:id="my-first-article">
<title>我的第一篇 PreTeXt 文档</title>
<!-- <p> 表示段落,最基本的文本容器 -->
<p>
欢迎使用 PreTeXt!这是一段普通文本。
你可以在段落中使用<em>强调</em>,
也可以使用数学公式:<m>E = mc^2</m>。
</p>
<p>
PreTeXt 使用 LaTeX 语法输入数学公式。
行内公式用 <m>...</m> 标签包裹,
行间公式用 <me>...</me>(me = math equation)。
</p>
<!-- <me> 是行间公式,自动居中显示 -->
<me>\int_0^1 x^2 \, dx = \frac{1}{3}</me>
</article>
</pretext>
执行结果:
将上述内容保存为 source/main.ptx(PreTeXt 文件扩展名为 .ptx),然后构建:
# 创建项目目录结构
mkdir -p my-first-article/source
# 将上面的 XML 保存为 source/main.ptx 后:
cd my-first-article
# 构建 HTML 版本
pretext build html
# 在浏览器中预览
pretext view html
预期输出:
# pretext build html 输出:
# 正在构建 html ...
# 输出已写入 output/html/my-first-article.html
#
# pretext view html 会自动打开浏览器显示结果。
# 页面中将显示:
# - 标题"我的第一篇 PreTeXt 文档"
# - 两段文本,第一段中的 E=mc² 被 MathJax 渲染为数学公式
# - 一个居中显示的积分公式
练习题:
1. 修改上面的例子,将 <article> 改为 <book>,观察构建结果有什么变化。
2. 添加一个新的段落,包含你喜欢的数学公式(提示:使用 <m> 标签包裹 LaTeX 公式)。
1.2 文档结构与章节组织
概念讲解:
在 1.1 中我们创建了最简单的单段落文章。现在学习如何组织多章节的文档结构。PreTeXt 提供了清晰的层级结构:
<book>→<chapter>→<section>→<subsection>→<subsubsection>(书籍结构)<article>→<section>→<subsection>(文章结构)
每个层级元素都需要一个 <title> 子元素。xml:id 属性用于交叉引用,建议为所有章节分配有意义的 ID。
代码示例:
<?xml version="1.0" encoding="UTF-8" ?>
<pretext>
<book xml:id="intro-to-sets">
<title>集合论入门</title>
<!-- 前置部分:书名页、前言等 -->
<frontmatter>
<titlepage>
<author>
<personname>张三</personname>
</author>
<date><today /></date>
</titlepage>
<preface>
<title>前言</title>
<p>本书介绍集合论的基本概念。</p>
</preface>
</frontmatter>
<!-- 第一章 -->
<chapter xml:id="ch-basic">
<title>基本概念</title>
<introduction>
<p>本章介绍集合的定义和基本运算。</p>
</introduction>
<section xml:id="sec-definition">
<title>集合的定义</title>
<p>
集合是一些确定的、不同的对象的无序汇集。
例如,<m>A = \{1, 2, 3\}</m> 是一个包含三个元素的集合。
</p>
</section>
<section xml:id="sec-operations">
<title>集合的运算</title>
<p>
两个集合 <m>A</m> 和 <m>B</m> 的并集定义为:
</p>
<me>A \cup B = \{x \mid x \in A \text{ 或 } x \in B\}</me>
<p>
交集定义为:
</p>
<me>A \cap B = \{x \mid x \in A \text{ 且 } x \in B\}</me>
</section>
</chapter>
<!-- 第二章 -->
<chapter xml:id="ch-advanced">
<title>进一步探讨</title>
<section xml:id="sec-power-set">
<title>幂集</title>
<p>
集合 <m>A</m> 的幂集 <m>\mathcal{P}(A)</m> 是 <m>A</m> 的所有子集的集合。
</p>
</section>
</chapter>
<!-- 后置部分:索引、解答等 -->
<backmatter>
<index />
</backmatter>
</book>
</pretext>
执行结果:
# 构建 HTML 和 PDF 两种格式
pretext build html
pretext build print
# 预览 HTML 版本
pretext view html
预期输出:
# HTML 版本将生成可导航的多页面网站:
# - 首页显示书名、作者和前言
# - 左侧导航栏显示章节结构
# - 第一章下有两个小节链接
# - 数学公式被 MathJax 正确渲染
#
# PDF 版本(print)将生成标准排版的印刷品:
# - 包含书名页、前言、章节
# - 页码、页眉、目录自动生成
练习题:
1. 为第二章再添加两个 section,内容自选(提示:可以写集合的笛卡尔积、补集等)。
2. 为每个 section 添加 xml:id 属性,确保 ID 具有描述性。
1.3 数学环境——定理、证明与定义
概念讲解:
PreTeXt 的核心优势之一是提供了丰富的数学语义标记。与 LaTeX 中定理环境的"排版指令"不同,PreTeXt 的标记明确区分定义(<definition>)、定理(<theorem>)、证明(<proof>)、示例(<example>)等语义类型。这使得转换器可以:
- 在 HTML 中以不同颜色/样式区分
- 在 PDF 中以传统学术排版呈现
- 在 Braille 中以适当方式编码
- 自动编号和生成索引
代码示例:
<?xml version="1.0" encoding="UTF-8" ?>
<pretext>
<article xml:id="math-demo">
<title>数学标记演示</title>
<!-- 定义:描述一个概念的含义 -->
<definition xml:id="def-even">
<title>偶数</title>
<p>
整数 <m>n</m> 称为<term>偶数</term>,
如果存在整数 <m>k</m> 使得 <m>n = 2k</m>。
</p>
</definition>
<!-- 定理:陈述一个可证明的真命题 -->
<theorem xml:id="thm-even-sum">
<statement>
<p>
两个偶数之和是偶数。
</p>
</statement>
<!-- proof 是 theorem 的子元素 -->
<proof>
<p>
设 <m>a</m> 和 <m>b</m> 是偶数。
由<xref ref="def-even" />,
存在整数 <m>j</m> 和 <m>k</m>
使得 <m>a = 2j</m> 且 <m>b = 2k</m>。
</p>
<p>
因此 <m>a + b = 2j + 2k = 2(j+k)</m>。
因为 <m>j+k</m> 是整数,
所以 <m>a+b</m> 是偶数。
</p>
</proof>
</theorem>
<!-- 示例:展示定理的应用 -->
<example xml:id="ex-even-sum">
<title>偶数之和示例</title>
<p>
<m>4</m> 和 <m>6</m> 都是偶数(因为 <m>4 = 2 \times 2</m>,
<m>6 = 2 \times 3</m>)。
它们的和 <m>4 + 6 = 10 = 2 \times 5</m> 确实是偶数,
验证了<xref ref="thm-even-sum" />。
</p>
</example>
<!-- 练习:供学生尝试的题目 -->
<exercise xml:id="exr-odd-sum">
<statement>
<p>
证明或反驳:两个奇数之和是偶数。
</p>
</statement>
<hint>
<p>设 <m>a = 2j+1</m>,<m>b = 2k+1</m>。</p>
</hint>
</exercise>
</article>
</pretext>
执行结果:
pretext build html
pretext view html
预期输出:
# HTML 页面中将显示:
# - "Definition 1.1 偶数" 蓝色框,包含定义内容
# - "Theorem 1.2" 绿色框,包含定理陈述
# - "Proof." 紧跟定理后,引用"Definition 1.1"会显示为可点击的 knowl
# - "Example 1.3 偶数之和示例" 橙色框
# - "Exercise 1" 练习题,带折叠的 hint 区域
# - 所有编号自动生成
# - 点击"xref"引用会弹出 knowl 显示引用内容
练习题:
1. 添加一个新的定义"奇数",然后添加一个定理"奇数与偶数之和是奇数"并给出证明。
2. 尝试使用其他数学标记:<lemma>(引理)、<corollary>(推论)、<remark>(注解)。
第二部分:进阶篇
2.1 交叉引用与 Knowl 系统
概念讲解:
在 1.3 中我们已经使用了 <xref> 进行交叉引用。现在深入了解 PreTeXt 的引用系统。PreTeXt 的 HTML 输出有一个独特功能:Knowl——可点击展开的引用气泡。当读者点击一个 <xref> 引用时,被引用的内容会在原位展开显示,无需跳转到其他页面。这在学术文档阅读中极大地提升了体验。
交叉引用的目标是通过 xml:id 属性标识的。任何 PreTeXt 元素都可以有 xml:id,然后通过 <xref ref="目标ID" /> 引用。
代码示例:
<?xml version="1.0" encoding="UTF-8" ?>
<pretext>
<article xml:id="xref-demo">
<title>交叉引用演示</title>
<section xml:id="sec-theorems">
<title>核心定理</title>
<theorem xml:id="thm-pythagorean">
<statement>
<p>
在直角三角形中,斜边的平方等于两直角边的平方和:
<me>a^2 + b^2 = c^2</me>
</p>
</statement>
</theorem>
<corollary xml:id="cor-isoceles">
<statement>
<p>
等腰直角三角形的斜边长为直角边的 <m>\sqrt{2}</m> 倍。
</p>
</statement>
<proof>
<p>
由<xref ref="thm-pythagorean" />,
设 <m>a = b</m>,则 <m>c^2 = 2a^2</m>,
即 <m>c = a\sqrt{2}</m>。
</p>
</proof>
</corollary>
</section>
<section xml:id="sec-applications">
<title>应用</title>
<p>
<!-- xref 自动生成引用文本,如 "Theorem 1.1" -->
<xref ref="thm-pythagorean" /> 是几何学中最重要的定理之一。
它的直接推论是<xref ref="cor-isoceles" />。
</p>
<p>
<!-- 可以引用章节 -->
在<xref ref="sec-theorems" />中我们介绍了基础定理。
</p>
<!-- 也可以引用公式 -->
<p>
公式 <xref ref="eq-quadratic" /> 给出了一元二次方程的求根公式。
</p>
<me xml:id="eq-quadratic">x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}</me>
</section>
</article>
</pretext>
注意事项:
- xml:id 必须全局唯一:在同一个文档中,任何两个元素的 xml:id 值不能相同。PreTeXt 会在验证时检查重复 ID。
- 引用不存在的 ID 会导致构建失败:如果 <xref ref="foo" /> 引用的 foo 不存在,构建时会报错。
- ID 命名建议:使用前缀+描述性名称的惯例,如 thm-(定理)、def-(定义)、sec-(章节)、eq-(公式)、ex-(示例)、exr-(练习)。
练习题:
1. 创建一个包含 3 个定义和 2 个定理的文档,在定理中引用定义,确保所有引用使用 knowl 方式展示。
2. 尝试引用一个公式(<me xml:id="...">)和一个练习(<exercise xml:id="...">)。
2.2 多格式构建与 Publication File
概念讲解:
PreTeXt 的核心价值是"一次编写,多格式发布"。在入门篇中我们已经用 pretext build html 和 pretext build print 构建了 HTML 和 PDF。现在学习如何控制构建行为。
PreTeXt-CLI 使用 project manifest(project.ptx)和 Publication File 来管理项目配置。project.ptx 定义了源文件位置、输出目标和 Publication File 路径。Publication File 控制每种输出格式的具体参数,如页面尺寸、字体大小、HTML 主题等。
代码示例:
首先创建项目配置文件 project.ptx:
<?xml version="1.0" encoding="UTF-8" ?>
<!-- project.ptx - 项目清单文件 -->
<project>
<!-- 指定源文件 -->
<source>
<directories>source</directories>
<file>main.ptx</file>
</source>
<!-- 定义多个输出目标 -->
<targets>
<!-- HTML 在线版 -->
<target name="html" format="html">
<publication>publication-html.xml</publication>
<output>output/html</output>
</target>
<!-- PDF 印刷版 -->
<target name="print" format="pdf">
<publication>publication-print.xml</publication>
<output>output/print</output>
</target>
<!-- EPUB 电子书 -->
<target name="epub" format="epub">
<publication>publication-epub.xml</publication>
<output>output/epub</output>
</target>
</targets>
</project>
Publication File for HTML(publication-html.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<!-- publication-html.xml - HTML 输出配置 -->
<publication>
<common>
<!-- 控制章节分割深度 -->
<chunking level="2" />
</common>
<html>
<!-- 选择 HTML 主题 -->
<style>modern</style>
<!-- 启用搜索功能 -->
<search>native</search>
<!-- 页面横幅设置 -->
<banner>
<left>集合论入门</left>
</banner>
</html>
</publication>
Publication File for PDF(publication-print.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<!-- publication-print.xml - PDF 输出配置 -->
<publication>
<common>
<chunking level="2" />
</common>
<latex>
<!-- 页面尺寸 -->
<page-shape>letter</page-shape>
<!-- 双面印刷 -->
<sides>two</sides>
<!-- 字号 -->
<font-size>11pt</font-size>
</latex>
</publication>
使用这些配置文件构建:
# 使用项目配置构建各格式
pretext build html # 使用 publication-html.xml 配置
pretext build print # 使用 publication-print.xml 配置
pretext build epub # 使用 publication-epub.xml 配置
# 预览特定格式
pretext view html
pretext view print
执行结果:
预期输出:
# pretext build html:
# 正在读取 project.ptx ...
# 正在使用 publication-html.xml 配置
# 正在转换 source/main.ptx → output/html/
# HTML 输出成功:output/html/index.html
# pretext build print:
# 正在读取 project.ptx ...
# 正在使用 publication-print.xml 配置
# 正在转换 source/main.ptx → output/print/
# 正在运行 pdflatex ...
# PDF 输出成功:output/print/main.pdf
注意事项:
- Publication File 不是必需的:没有 Publication File 时,PreTeXt 使用默认配置构建。Publication File 用于需要精细控制的场景。
- LaTeX 编译可能需要多次运行:生成 PDF 时,交叉引用和索引需要多次运行 pdflatex。PreTeXt-CLI 会自动处理这个问题。
- EPUB 验证:构建 EPUB 后建议运行 epubcheck 验证输出文件的标准合规性。
练习题:
1. 创建 project.ptx 和两个 Publication File,分别配置 HTML 的"modern"主题和 PDF 的 A4 页面尺寸。
2. 使用 pretext build 分别构建 HTML 和 PDF,对比两种输出的差异。
第三部分:高级篇
3.1 WeBWorK 交互式习题集成
概念讲解:
PreTeXt 的独特优势之一是与 WeBWorK(在线作业系统)的深度集成。在 PreTeXt 源文件中,可以嵌入 WeBWorK 习题,这些习题在 HTML 输出中为可交互的在线练习(学生可以输入答案并获得即时反馈),在 PDF 输出中为静态打印版本。
这种"同一内容,不同交互模式"的设计体现了 PreTeXt "一次编写,处处发布"的理念。
代码示例:
<?xml version="1.0" encoding="UTF-8" ?>
<pretext>
<article xml:id="webwork-demo">
<title>WeBWorK 交互式习题演示</title>
<section>
<title>微积分练习</title>
<!-- 嵌入 WeBWorK 习题 -->
<exercise xml:id="ww-derivative">
<webwork>
<statement>
<p>
求函数 <m>f(x) = 3x^4 - 2x^2 + 7</m> 的导数
<m>f'(x)</m>。
</p>
<p>
<m>f'(x) =</m>
<var name="$ans" width="20" category="formula" />
</p>
</statement>
<setup>
<!-- 正确答案的定义 -->
<var name="$ans">
<static>12x^3 - 4x</static>
</var>
</setup>
<hint>
<p>
使用幂法则:<m>\frac{d}{dx}x^n = nx^{n-1}</m>。
</p>
</hint>
<solution>
<p>
对每一项分别求导:
</p>
<p>
<m>\frac{d}{dx}(3x^4) = 12x^3</m>,
<m>\frac{d}{dx}(-2x^2) = -4x</m>,
<m>\frac{d}{dx}(7) = 0</m>。
</p>
<p>
因此 <m>f'(x) = 12x^3 - 4x</m>。
</p>
</solution>
</webwork>
</exercise>
</section>
</article>
</pretext>
注意事项:
- WeBWorK 需要服务器:完整的 WeBWorK 交互功能需要 WeBWorK 服务器。在纯本地环境中,PreTeXt 可以生成"静态"版本的 WeBWorK 习题(HTML 中显示题目和答案输入框,PDF 中显示完整题目和解答)。
- PG 语法限制:WeBWorK 的 PG(Problem Generator)语法基于 Perl。PreTeXt 提供了 Perl-free 模式,允许用纯 XML 描述简单习题。
- 答案格式:category="formula" 允许学生输入数学表达式,WeBWorK 会自动评估等价性。
练习题:
1. 创建一个 WeBWorK 习题,要求学生计算定积分 <var name="$ans" category="number" />(数值型答案)替代 category="formula"。
3.2 图像处理与数学可视化
概念讲解:
STEM 教材中图表是必不可少的。PreTeXt 支持多种图像来源: - 栅格图像(PNG、JPG)— 外部文件或截图 - 矢量图形(SVG、PDF)— 高质量可缩放图形 - 源码描述的图像(Asymptote、TikZ、Sage、Mermaid)— 从代码自动生成
源码描述的图像是 PreTeXt 的强大特性:作者在 XML 中嵌入 Asymptote 或 TikZ 代码,PreTeXt 在构建时自动调用相应工具生成图像。这意味着修改图像只需修改代码,无需手动导出和替换文件。
代码示例:
<?xml version="1.0" encoding="UTF-8" ?>
<pretext>
<article xml:id="image-demo">
<title>图像处理演示</title>
<section>
<title>使用图像</title>
<!-- 方式 1:外部栅格图像 -->
<figure xml:id="fig-external">
<caption>一张外部图片</caption>
<image source="images/photo.png" width="60%" />
</figure>
<!-- 方式 2:TikZ 代码生成矢量图 -->
<figure xml:id="fig-tikz-triangle">
<caption>直角三角形示意图</caption>
<image xml:id="img-triangle" width="50%">
<latex-image>
<!-- TikZ 代码 -->
\begin{tikzpicture}
% 绘制直角三角形
\draw[thick] (0,0) -- (4,0) -- (4,3) -- cycle;
% 标注直角符号
\draw (3.7,0) -- (3.7,0.3) -- (4,0.3);
% 标注边长
\node[below] at (2,0) {$a$};
\node[right] at (4,1.5) {$b$};
\node[above left] at (2,1.5) {$c$};
\end{tikzpicture}
</latex-image>
</image>
</figure>
<!-- sidebyside:并排展示多张图 -->
<sidebyside widths="45% 45%">
<image source="images/plot-a.png">
<description>函数 A 的图像</description>
</image>
<image source="images/plot-b.png">
<description>函数 B 的图像</description>
</image>
</sidebyside>
</section>
</article>
</pretext>
注意事项:
- 图像生成需要额外工具:TikZ 图像需要 LaTeX,Asymptote 图像需要 Asymptote 软件。使用 pretext generate 命令可批量生成所有源码描述的图像。
- 图像描述(description)对无障碍至关重要:<description> 标签为视觉障碍者提供图像的文字描述。屏幕阅读器会朗读这段描述。这是 PreTeXt 无障碍设计的重要组成部分。
- 构建顺序:先运行 pretext generate(生成图像),再运行 pretext build(构建文档)。
练习题:
1. 使用 TikZ 创建一个圆的图形,标注圆心和半径。
2. 为你的图形添加 <description> 无障碍描述。
3.3 最佳实践
- 模块化源文件:使用 XML 实体(XInclude)将大型文档拆分为多个文件。例如,每章一个文件,通过
<xi:include>引入主文件。PreTeXt 原生支持 XInclude 模块化。
<!-- main.ptx 主文件 -->
<pretext>
<book xml:id="my-book">
<title>我的书</title>
<!-- 使用 XInclude 引入各章节 -->
<xi:include href="chapter-01.ptx" />
<xi:include href="chapter-02.ptx" />
</book>
</pretext>
-
使用 Git 管理源文件:将 PreTeXt XML 源文件纳入 Git 版本控制。
pretext deploy可以自动将 HTML 输出部署到 GitHub Pages,配合 GitHub Actions 实现自动构建。 -
始终先验证再构建:使用
pretext validate在构建前检查源文件是否符合 Schema。这能捕获大部分标记错误,避免构建时的隐晦报错。 -
为所有数学环境分配 xml:id:即使是暂时不引用的定理和定义,也分配有意义的 ID。这方便后续交叉引用,也使文档结构更清晰。
-
无障碍描述不可省略:每个图像都应有
<description>。使用<idx>标签为索引添加条目。这些步骤在编写时稍显繁琐,但对最终用户(特别是视觉障碍读者)至关重要。
第四部分:实战项目
项目需求
构建一个完整的线性代数入门教材单章,综合运用以下知识点: 1. PreTeXt 文档结构与章节组织(1.2) 2. 数学环境——定理、证明与定义(1.3) 3. 交叉引用与 Knowl 系统(2.1) 4. TikZ 图像生成(3.2) 5. Publication File 多格式配置(2.2)
教材需要同时生成 HTML(在线阅读版)和 PDF(印刷版)两种输出。
项目设计
- 主题:向量——从定义到运算
- 结构:1 章 2 节,每节包含定义、定理、证明、示例和练习
- 图像:使用 TikZ 绘制向量示意图
- 交叉引用:定义和定理之间相互引用
- 输出:HTML(modern 主题)+ PDF(A4 双面印刷)
完整实现代码
文件 1:project.ptx
<?xml version="1.0" encoding="UTF-8" ?>
<project>
<source>
<directories>source</directories>
<file>main.ptx</file>
</source>
<targets>
<target name="html" format="html">
<publication>publication-html.xml</publication>
<output>output/html</output>
</target>
<target name="print" format="pdf">
<publication>publication-print.xml</publication>
<output>output/print</output>
</target>
</targets>
</project>
文件 2:publication-html.xml
<?xml version="1.0" encoding="UTF-8" ?>
<publication>
<common>
<chunking level="2" />
</common>
<html>
<style>modern</style>
<search>native</search>
<banner>
<left>线性代数入门</left>
</banner>
</html>
</publication>
文件 3:publication-print.xml
<?xml version="1.0" encoding="UTF-8" ?>
<publication>
<common>
<chunking level="2" />
</common>
<latex>
<page-shape>a4</page-shape>
<sides>two</sides>
<font-size>11pt</font-size>
</latex>
</publication>
文件 4:source/main.ptx(主源文件)
<?xml version="1.0" encoding="UTF-8" ?>
<pretext>
<book xml:id="linear-algebra-intro">
<title>线性代数入门</title>
<frontmatter>
<titlepage>
<author>
<personname>张三</personname>
</author>
<date><today /></date>
</titlepage>
</frontmatter>
<chapter xml:id="ch-vectors">
<title>向量</title>
<introduction>
<p>
向量是线性代数的基本研究对象。本章介绍向量的定义、
几何表示和基本运算。
</p>
</introduction>
<!-- 知识点 1 & 2:文档结构 + 数学环境 -->
<section xml:id="sec-vector-def">
<title>向量的定义</title>
<definition xml:id="def-vector">
<title>向量</title>
<p>
一个 <m>n</m> 维向量是一个有序的 <m>n</m> 元组
<m>\mathbf{v} = (v_1, v_2, \ldots, v_n)</m>,
其中 <m>v_i</m> 称为向量的第 <m>i</m> 个分量。
</p>
</definition>
<example xml:id="ex-vectors">
<title>向量示例</title>
<p>
<m>\mathbf{u} = (1, 2, 3)</m> 是一个 3 维向量,
<m>\mathbf{v} = (-1, 0, 4)</m> 也是一个 3 维向量。
</p>
</example>
<!-- 知识点 4:TikZ 图像 -->
<figure xml:id="fig-2d-vectors">
<caption>二维平面中的向量</caption>
<image xml:id="img-2d-vectors" width="60%">
<latex-image>
\begin{tikzpicture}[scale=0.8]
% 坐标轴
\draw[->] (-0.5,0) -- (4.5,0) node[right] {$x$};
\draw[->] (0,-0.5) -- (0,3.5) node[above] {$y$};
% 向量 u
\draw[->, thick, blue] (0,0) -- (3,2)
node[above right] {$\mathbf{u} = (3,2)$};
% 向量 v
\draw[->, thick, red] (0,0) -- (1,3)
node[above left] {$\mathbf{v} = (1,3)$};
% 分量虚线
\draw[dashed, blue] (3,0) -- (3,2);
\draw[dashed, blue] (0,2) -- (3,2);
\draw[dashed, red] (1,0) -- (1,3);
\draw[dashed, red] (0,3) -- (1,3);
\end{tikzpicture}
</latex-image>
</image>
</figure>
</section>
<!-- 知识点 3:交叉引用 -->
<section xml:id="sec-vector-ops">
<title>向量的运算</title>
<definition xml:id="def-vector-add">
<title>向量加法</title>
<p>
设 <m>\mathbf{u} = (u_1, \ldots, u_n)</m> 和
<m>\mathbf{v} = (v_1, \ldots, v_n)</m> 是两个
<m>n</m> 维向量(见<xref ref="def-vector" />),
它们的和定义为:
<me>\mathbf{u} + \mathbf{v} = (u_1 + v_1, \ldots, u_n + v_n)</me>
</p>
</definition>
<theorem xml:id="thm-commutative">
<statement>
<p>
向量加法满足交换律:
<m>\mathbf{u} + \mathbf{v} = \mathbf{v} + \mathbf{u}</m>。
</p>
</statement>
<proof>
<p>
由<xref ref="def-vector-add" />,
<me>\mathbf{u} + \mathbf{v}
= (u_1 + v_1, \ldots, u_n + v_n)</me>
而
<me>\mathbf{v} + \mathbf{u}
= (v_1 + u_1, \ldots, v_n + u_n)</me>
因为实数加法满足交换律
(<m>u_i + v_i = v_i + u_i</m>),
所以 <m>\mathbf{u} + \mathbf{v} = \mathbf{v} + \mathbf{u}</m>。
</p>
</proof>
</theorem>
<example xml:id="ex-vector-add">
<title>向量加法示例</title>
<p>
回顾<xref ref="ex-vectors" />中的向量,
<me>\mathbf{u} + \mathbf{v}
= (1+(-1), 2+0, 3+4)
= (0, 2, 7)</me>
这验证了<xref ref="thm-commutative" />。
</p>
</example>
<exercise xml:id="exr-scalar-mult">
<statement>
<p>
定义标量乘法为
<m>c \cdot \mathbf{v} = (cv_1, \ldots, cv_n)</m>。
证明标量乘法对向量加法满足分配律:
<m>c(\mathbf{u} + \mathbf{v})
= c\mathbf{u} + c\mathbf{v}</m>。
</p>
</statement>
</exercise>
</section>
</chapter>
<backmatter>
<index />
</backmatter>
</book>
</pretext>
构建命令:
# 在项目根目录下执行
# 生成 TikZ 图像
pretext generate
# 构建 HTML 和 PDF
pretext build html
pretext build print
# 预览
pretext view html
pretext view print
代码解析
本实战项目综合运用了教程中的 5 个知识点:
-
文档结构与章节组织(1.2):整个项目使用
<book>→<chapter>→<section>的层级结构,包含<frontmatter>和<backmatter>。 -
数学环境(1.3):使用了
<definition>(向量和向量加法的定义)、<theorem>(交换律定理)、<proof>(证明过程)、<example>(具体示例)和<exercise>(练习题)五种数学语义标记。 -
交叉引用与 Knowl 系统(2.1):
<xref ref="def-vector" />引用向量定义,<xref ref="thm-commutative" />引用交换律定理。在 HTML 输出中,这些引用显示为可点击的 knowl 气泡。 -
TikZ 图像生成(3.2):使用
<latex-image>标签嵌入 TikZ 代码,绘制二维平面中的向量示意图。<figure>提供了标题和编号,<caption>描述图像内容。 -
Publication File 多格式配置(2.2):
project.ptx定义了两个输出目标(HTML 和 PDF),各自使用独立的 Publication File 控制输出参数。HTML 使用 modern 主题,PDF 使用 A4 双面印刷。
扩展挑战
-
添加 WeBWorK 习题:在练习部分嵌入一个 WeBWorK 交互式习题,让学生输入向量加法的答案并自动评分。(提示:参考 3.1 节的 WeBWorK 语法)
-
支持 Braille 输出:添加一个新的 Publication File 配置 Braille 输出,构建盲文版本。研究 Braille 输出中的数学公式编码方式(Nemeth 编码)。
-
XInclude 模块化:将每个
<section>拆分为独立的.ptx文件,使用<xi:include>引入主文件,实现大型文档的模块化管理。
第五部分:常见问题与排查指南
常见错误及解决方案
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
element "foo" not allowed here |
使用了 Schema 不允许的标签或嵌套方式 | 运行 pretext validate 检查具体位置,对照 PreTeXt Guide 确认正确的元素嵌套规则 |
xref target "bar" not found |
<xref> 引用的 xml:id 不存在 |
检查 xml:id 拼写,确认目标元素在同一个文档中且 ID 唯一 |
xsltproc: command not found |
系统未安装 xsltproc | macOS: xcode-select --install;Linux: sudo apt install xsltproc;Windows: 安装 Cygwin 或使用 WSL |
pdflatex: command not found |
未安装 LaTeX 发行版 | 安装 TeX Live 或 MiKTeX(参见环境搭建指南) |
I/O error : Attempt to load network entity |
XML 文件中引用了网络资源但无法访问 | 检查 XML 声明和 DTD 引用,确保 project.ptx 中路径正确 |
! LaTeX Error: File 'xxx.sty' not found |
LaTeX 宏包缺失 | 安装对应的 texlive 包:sudo apt install texlive-latex-extra(Ubuntu)或使用 TeX Live 完整安装 |
duplicate xml:id "foo" |
同一文档中有重复的 xml:id 值 |
为每个元素分配唯一的 xml:id,使用前缀命名约定(如 thm-、def-) |
Image generation failed for Asymptote/TikZ |
图像生成工具未安装或版本不兼容 | 确认 Asymptote(asy)或 LaTeX 已安装。使用 pretext generate --verbose 查看详细错误 |
pretext: command not found |
PreTeXt-CLI 未正确安装或虚拟环境未激活 | 重新激活虚拟环境:source pretext-env/bin/activate,然后 pip install pretext |
schema validation error |
XML 标记不符合 PreTeXt Schema | 运行 pretext validate 获取详细错误位置和提示。常见原因:标签拼写错误、缺少必需属性、嵌套不正确 |
调试技巧
-
使用
pretext validate先验证再构建:这是最重要的调试策略。Schema 验证能在构建前捕获大部分标记错误(拼写、嵌套、缺失属性),错误信息包含行号和具体问题描述。养成"修改后先验证"的习惯可以节省大量时间。 -
用
--verbose标志获取详细日志:当构建失败但错误信息不够明确时,使用pretext build html --verbose可以看到完整的构建过程日志,包括 XSLT 转换和 LaTeX 编译的详细输出,有助于定位问题。 -
从小处开始,逐步添加内容:如果大型文档构建失败且难以定位问题,创建一个最小可复现示例——只包含根元素和出错的部分元素。逐步添加内容直到复现错误,这通常能快速定位问题所在。
第六部分:学习路线推荐
官方文档推荐阅读顺序
- PreTeXt Guide 第 1 章 "Why PreTeXt?" — 理解设计哲学和 11 条指导原则,建立正确的使用心态
- 第 2 章 "Getting Started Tutorial" — 跟随官方教程创建第一个文档,掌握基本工作流
- 第 3 章 "Overview of Features" — 浏览 PreTeXt 的全部功能特性,了解能做什么
- 第 4 章 "Topics" — 按需查阅具体标记元素的用法(数学、图像、列表、交叉引用等)
- 第 5 章 "Processing, Tools and Workflow" — 深入理解 CLI 工具和构建流程
- 第 6 章 "PreTeXt Vocabulary Specification" — Schema 规范参考,需要时查阅
- 第 29-34 章 — 各输出格式的 Publisher's Guide(HTML、PDF、EPUB、Braille、Slides 等)
推荐进阶资源
- The PreTeXt Guide PDF — 官方完整指南(PDF 格式,由 PreTeXt 自身生成),是 PreTeXt 最大的"用 PreTeXt 写的文档"案例
- Oscar Levin - PreTeXt 教程 — 社区贡献者编写的实用教程,以《Discrete Mathematics: An Open Introduction》作者的第一手经验分享 PreTeXt 写作技巧
- Rob Beezer YouTube 系列 — PreTeXt 创始人的演讲视频,涵盖项目历史、设计理念和未来规划,适合深入理解项目愿景
- pretext-support Google Group — 社区支持论坛,遇到问题可在此搜索或提问。Rob Beezer 和其他核心开发者经常在此回复