自定义列表

概述

除了内置的3种列表类型外,您还可以构建一个完全自定义的项目显示方式。这种自定义显示可以生成任何HTML,并且可以选择仍然利用列表提供的排序、过滤和分页功能。

列表模板

要构建自定义列表显示,您需要创建一个EJS模板,该模板将用于生成传递给模板的一组项目的HTML。EJS模板允许您使用普通的javascript生成HTML,从而可以轻松地循环遍历项目并在自定义HTML中输出它们的值。

要使用自定义模板,请在列表的 template 选项中传递它:

listing:
  template: gallery.ejs

当使用自定义模板的列表被渲染时,列表内容将被读取并处理成一组传递给模板的项进行渲染。例如,在这种情况下,posts目录中的所有文档将被读取为项目并传递给 gallery.ejs 模板。

listing:
  contents: posts
  template: gallery.ejs

一个简单的模板,用于输出文档列表,可能如下所示:

<ul>
<% for (const item of items) { %>
  <li><a href="<%- item.path %>"><%= item.title %></a></li>
<% } %>
</ul>

这将产生如下简单的HTML输出:

渲染时,上述模板将接收一个名为 items 的列表项数组。当列表的内容从一组文档中加载时,每个项目将填充在列表字段中描述的字段。此外,文档元数据中包含的任何其他字段都将作为项目的属性传递,从而可以在文档和列表显示中使用自定义元数据。

Note

请注意,Quarto使用 lodash 来渲染EJS模板。lodash 在模板中对文本进行HTML转义时使用不同的语法。

HTML转义值:   <%- value %>
HTML未转义值: <%= value %>

元数据列表

列表的 contents 选项通常包含路径或通配符列表,但它也可以包含元数据。当内容是元数据时,元数据将被读取为项目并传递给模板。例如:

listing:
  template: custom.ejs
  contents:
    - name: 第一项
      href: https://www.quarto.org
      custom-field: 自定义值
    - name: 第二项
      href: https://www.rstudio.org
      custom-field: 第二个自定义值

可以使用以下方式渲染:

```{=html}
<ul>
<% for (const item of items) { %>
  <li>
    <a href="<%- item.href %>"><%= item.name %></a><br/>
    <%= item['custom-field'] %>
  </li>
<% } %>
</ul>
```

这将产生如下简单的HTML显示:

元数据文件列表

列表的 contents 选项也可以指向一个或多个包含元数据的 yaml 文件。在这种情况下,元数据将从文件中读取为项目并传递给模板。例如:

listing:
  template: custom.ejs
  contents:
    - items.yml

其中 items.yml 的内容是:

- name: 第一项
  href: https://www.quarto.org
  custom-field: 自定义值
- name: 第二项
  href: https://www.rstudio.org
  custom-field: 第二个自定义值

模板示例

本网站的部分内容是使用自定义列表构建的。最好的起点是我们的画廊,这是一个使用自定义模板和元数据文件构建的列表。您可以在我们的Github仓库中查看用于创建画廊页面的源代码。

文件 描述
gallery.yml 控制画廊列表中显示哪些项目的元数据。
gallery.ejs 用于在页面上显示项目的模板。
index.qmd 配置并将列表放置在 #gallery div 中的Quarto文档。

排序、过滤和分页

默认情况下,自定义列表模板的排序、过滤和分页是禁用的,但通过在模板和列表选项中进行一些简单的更改,您可以为自定义列表添加此功能。为此,您需要在自定义模板中包含以下三项内容: 1. 在包含项目列表的HTML标签中包含一个list类。

  1. 对于每个项目,在包含该项目的HTML标签中包含<%= metadataAttrs(item) %>。这将允许Quarto编写用于排序和过滤的自定义属性。

  2. 在每个项目中,包含一个类,用于标识其文本表示项目字段内容的标签。该类必须是字段名称前缀为listing-,例如,其内部文本是item.name的标签应包含一个类listing-name

例如,我们可以将上述custom.ejs模板修改如下:

<ul class="list">
<% for (const item of items) { %>
  <li <%= metadataAttrs(item) %>>
    <a href="<%- item.href %>" class="listing-name"><%= item.name %></a><br/>
    <span class="listing-custom-field"><%= item['custom-field'] %><span>
  </li>
<% } %>
</ul>

一旦您在模板中包含了这些项目,您就可以在列表中启用以下选项:

listing:
  sort-ui: true
  filter-ui: true
  page-size: 10

现在,UI元素将出现在页面上,并且应该与您的自定义列表正确交互。

字段显示名称

您可能希望为字段提供自定义显示名称,以提供比字段名称更好的名称。例如,字段名称将出现在排序UI中。您可以使用field-display-names创建从字段到显示名称的映射。例如:

listing:
  template: custom.ejs
  contents:
    - items.yml
  sort-ui: true
  filter-ui: true
  page-size: 10
  field-display-names:
    name: "名称"
    custom-field: "自定义字段"

日期排序和格式化

为了正确格式化和排序日期值,您可以在项目字段中指定类型信息。如果您指定字段为日期,它将自动使用指定的日期格式(默认或使用date-format指定)进行格式化,并支持按升序或降序进行日期排序。如果您指定字段为数字,它将支持升序和降序的数值排序。

您可以按如下方式指定字段类型:

listing:
  template: custom.ejs
  contents:
    - items.yml
  field-types:
    custom-date: date
    custom-number: number

必需字段

由于列表是使用在其他文档中指定或通过元数据指定的字段生成的,因此确保必需字段存在可能会有所帮助。您可以按如下方式标注必需字段:

listing:
  template: custom.ejs
  contents:
    - items.yml
  field-required: [name, custom-field]

如果渲染列表页面时内容中缺少任何必需字段的值,将抛出一个错误,指出所需的字段以及省略该字段的文件或元数据。

模板参数

您还可以通过使用参数来控制其行为,使自定义模板更加动态。您可以使用template-params选项为自定义模板提供参数,例如:

listing:
  template: custom.ejs
  contents:
    - items.yml
  template-params:
    param1: "param-value"

然后,可以在模板中使用<%= templateParams.param1 %>访问模板参数。例如,我们可以将上述custom.ejs模板修改如下:

<h3><%= templateParams.param1 %></h3>
<ul class="pub-list list">
  <% for (const item of items) { %>
      <li <%= metadataAttrs(item) %>>
        <span class="listing-title"><%= item.title %>.</span>
      </li>
  <% } %>
</ul>