处理器

扩展 Lume 自定义处理器的指南

处理器是一个函数,用于在页面渲染之后转换页面内容。让我们看一个使用处理器来压缩 HTML 页面的例子:

function minifyHTML(pages) {
  for (const page of pages) {
    page.content = minify(page.content);
  }
}

如果你想使用这个处理器来构建你的站点,你可以在 _config.js 文件中注册它:

site.process([".html"], minifyHTML);

现在,所有的 HTML 页面都会被压缩。

页面对象

正如你在前面的例子中看到的,该函数接收一个页面对象数组。页面对象不仅包含页面内容,还包含更多数据:

function process(pages) {
  for (const page of pages) {
    page.content; // 页面的内容
    page.document; // 解析后的 HTML 代码,用于使用 DOM API
    page.src; // 关于此页面的源文件的信息
    page.data; // 此页面的所有可用数据(前端 matter 与 _data 合并)
  }
}

例如,假设你只想压缩 minify 值为 true 的页面:

site.process([".html"], (pages) => {
  for (const page of pages) {
    if (page.data.minify) {
      page.content = minify(page.content);
    }
  }
});

使用 DOM API

你可以使用 DOM API(由 deno-dom 驱动),使用诸如 querySelectorsetAttribute 等方法来修改 HTML 代码。例如,让我们创建一个处理器来自动为所有图像添加 alt 属性:

site.process([".html"], (pages) => {
  for (const page of pages) {
    for (const img of page.document.querySelectorAll("img")) {
      if (!img.hasAttribute("alt")) {
        img.setAttribute("alt", "This is a random alt");
      }
    }
  }
});

处理 assets

对于非 HTML 页面(例如 CSS 或 JavaScript 文件),你可以使用处理器来编译 CSS,压缩 JavaScript 代码或压缩图像。

site.process([".js"], function (pages) {
  for (const page of pages) {
    page.content = myBundler(page.content);

    // 将 .min 追加到文件名
    // 以便它将保存为 example.min.js
    page.data.url = page.data.url.replace(/\.js$/, ".min.js");
  }
});

Note

确保你想要处理的文件扩展名已预先加载。 有关如何注册新加载器的更多信息,请参阅 如何加载 assets

预处理器

如果你需要在渲染之前执行一个函数(例如,配置自定义模板引擎或向某些页面添加额外数据),你可以使用预处理器。预处理器的工作方式类似于处理器,但它们在渲染之前执行。

让我们创建一个预处理器来包含一个带有源文件名的变量:

site.preprocess([".html"], (pages) => {
  for (const page of pages) {
    page.data.filename = page.src.path + page.src.ext;
  }
});

动态创建页面

处理器可以生成额外的页面(或删除它们)。(预)处理器的第二个参数包含一个包含站点所有页面的数组。你可以修改此数组以动态添加或删除页面。例如:

import { Page } from "lume/core/file.ts";

site.process([".css"], (filteredPages, allPages) => {
  for (const page of filteredPages) {
    // 压缩 css 内容
    const { code, map } = myCssMinifier(page.content);

    // 更新页面内容
    page.content = code;

    // 创建一个带有 sourcemap 的新页面
    const pageMap = Page.create({
      url: page.data.url + ".map",
      content: map,
    });

    // 将页面添加到站点
    allPages.push(pageMap);
  }
});

动态删除页面

要动态删除页面,你必须从第二个参数的页面数组中删除它:

// 删除所有 language = "en" 的 html 页面
site.process([".html"], (filteredPages, allPages) => {
  for (const page of filteredPages) {
    if (page.data.lang === "en") {
      // 在 allPages 数组中搜索页面并删除它
      allPages.splice(allPages.indexOf(page), 1);
    }
  }
});

处理器和预处理器的工作原理

处理器和预处理器都与文件扩展名(.html.js 等)相关联。为了确定页面是否必须使用已注册的处理器或预处理器,Lume 搜索输入文件(如 .md.vto)或输出文件(如 .html.css)的扩展名。

另一个有趣的事情是它们按照定义的顺序执行。这允许将不同的处理器链接到相同的文件扩展名。例如:用于 .css 扩展名的两个处理器,一个用于编译代码,另一个用于压缩。

全局(预)处理器

如果你想为所有页面运行一个处理器或预处理器,请在第一个参数中使用 *

site.process("*", processAllPages);