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 htmlpretext build print 构建了 HTML 和 PDF。现在学习如何控制构建行为。

PreTeXt-CLI 使用 project manifestproject.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 习题,要求学生计算定积分 \int_0^2 x^3 \, dx 的值(答案为 4)。 2. 尝试使用 <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 最佳实践

  1. 模块化源文件:使用 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>
  1. 使用 Git 管理源文件:将 PreTeXt XML 源文件纳入 Git 版本控制。pretext deploy 可以自动将 HTML 输出部署到 GitHub Pages,配合 GitHub Actions 实现自动构建。

  2. 始终先验证再构建:使用 pretext validate 在构建前检查源文件是否符合 Schema。这能捕获大部分标记错误,避免构建时的隐晦报错。

  3. 为所有数学环境分配 xml:id:即使是暂时不引用的定理和定义,也分配有意义的 ID。这方便后续交叉引用,也使文档结构更清晰。

  4. 无障碍描述不可省略:每个图像都应有 <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. 文档结构与章节组织(1.2):整个项目使用 <book><chapter><section> 的层级结构,包含 <frontmatter><backmatter>

  2. 数学环境(1.3):使用了 <definition>(向量和向量加法的定义)、<theorem>(交换律定理)、<proof>(证明过程)、<example>(具体示例)和 <exercise>(练习题)五种数学语义标记。

  3. 交叉引用与 Knowl 系统(2.1)<xref ref="def-vector" /> 引用向量定义,<xref ref="thm-commutative" /> 引用交换律定理。在 HTML 输出中,这些引用显示为可点击的 knowl 气泡。

  4. TikZ 图像生成(3.2):使用 <latex-image> 标签嵌入 TikZ 代码,绘制二维平面中的向量示意图。<figure> 提供了标题和编号,<caption> 描述图像内容。

  5. Publication File 多格式配置(2.2)project.ptx 定义了两个输出目标(HTML 和 PDF),各自使用独立的 Publication File 控制输出参数。HTML 使用 modern 主题,PDF 使用 A4 双面印刷。

扩展挑战

  1. 添加 WeBWorK 习题:在练习部分嵌入一个 WeBWorK 交互式习题,让学生输入向量加法的答案并自动评分。(提示:参考 3.1 节的 WeBWorK 语法)

  2. 支持 Braille 输出:添加一个新的 Publication File 配置 Braille 输出,构建盲文版本。研究 Braille 输出中的数学公式编码方式(Nemeth 编码)。

  3. 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 获取详细错误位置和提示。常见原因:标签拼写错误、缺少必需属性、嵌套不正确

调试技巧

  1. 使用 pretext validate 先验证再构建:这是最重要的调试策略。Schema 验证能在构建前捕获大部分标记错误(拼写、嵌套、缺失属性),错误信息包含行号和具体问题描述。养成"修改后先验证"的习惯可以节省大量时间。

  2. --verbose 标志获取详细日志:当构建失败但错误信息不够明确时,使用 pretext build html --verbose 可以看到完整的构建过程日志,包括 XSLT 转换和 LaTeX 编译的详细输出,有助于定位问题。

  3. 从小处开始,逐步添加内容:如果大型文档构建失败且难以定位问题,创建一个最小可复现示例——只包含根元素和出错的部分元素。逐步添加内容直到复现错误,这通常能快速定位问题所在。


第六部分:学习路线推荐

官方文档推荐阅读顺序

  1. PreTeXt Guide 第 1 章 "Why PreTeXt?" — 理解设计哲学和 11 条指导原则,建立正确的使用心态
  2. 第 2 章 "Getting Started Tutorial" — 跟随官方教程创建第一个文档,掌握基本工作流
  3. 第 3 章 "Overview of Features" — 浏览 PreTeXt 的全部功能特性,了解能做什么
  4. 第 4 章 "Topics" — 按需查阅具体标记元素的用法(数学、图像、列表、交叉引用等)
  5. 第 5 章 "Processing, Tools and Workflow" — 深入理解 CLI 工具和构建流程
  6. 第 6 章 "PreTeXt Vocabulary Specification" — Schema 规范参考,需要时查阅
  7. 第 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 和其他核心开发者经常在此回复