Article original : Working with Collections de Philip Borenstein

Le générateur de site statique open source Eleventy est à la différence d’autres générateurs — comme Jekyll ou Hugo — beaucoup moins opiniâtre. Là où ces deux générateurs vont imposer la manière dont vous pouvez créer des collections de documents (appelées sections de contenu dans Hugo), Eleventy lui vous laisse le choix.

Dans Eleventy les collections permettent de grouper des articles selon divers critères. Une collection pourrait désigner une série d’articles. Un autre collection pourrait regrouper les articles à propos de livres. Une troisième collection pourrait rassembler tous les contenus d’un même répertoire.

Eleventy vous permet de créer des collections de deux manières :

Les collections à base de tags

Toutes les pages qui partagent un même tag appartiennent à la même collection. Un modèle avec le front matter suivant va générer des pages dans les collections books et reviews.

---
title: Finding Oz
category: Culture
tags:
- books
- reviews
---
. . .

Dans un modèle, on accède aux collections par leur nom, en tant que propriété de l’object global collections.

<p>
  Le titre de cette page est :
  {{ collections.books[0].data.title }}
</p>

On utilise généralement les collections dans des boucles afin d’itérer sur chaque élément de la collection.

{% for post in collections.books %}
  {{ post.data.title }}
  {{ post.url }}
  {{ post.data.category }}
  {{ post.data.tags }}
  {{ post.date }}
{% endfor %}

L’objet collections lui, ressemble à ça :

{
  "all": [...],
  "nav": [...],
  "books": [
    {
      "inputPath": "./src/articles/finding-oz.md",
      "outputPath": "_site/articles/finding-oz/index.html",
      "fileSlug": "finding-oz",
      "data": {...},
      "date": "2009-08-07T13:52:12.000Z",
      "url": "/articles/finding-oz/",
      "templateContent": "<p>As with most books ... much about The Wizard of Oz</li>\n</ul>\n",
      "template": {...}
    },
    ...
  ],
  "programming": [...],
}

Chaque propriété est un tableau d’objets d’éléments de collection (également appelés objets modèle dans la documentation).

La collection spéciale all représente un tableau de tous les objets page générés par Eleventy.

propriétés des éléments de collection
PropriétéDescription
inputPathChemin vers ce fichier incluant le répertoire source.
./src/articles/finding-oz.md
outputPathChemin du fichier généré.
articles/finding-oz/index.html
fileSlugVersion courte en fonction du nom et de l’emplacement du fichier. En fonction des règles.
finding-oz
dataDonnées du front matter de la page rendue. Les variables globales disponibles pour chaque page.
dateLa date du fichier au format UTC. Voir les règles.
2019-01-27T13:52:12.000Z
urlChemin vers le contenu. N’inclus pas le protocole et le nom d’hôte.
/articles/finding-oz/
templateContentLe contenu généré de la page, n’inclut pas les balises enveloppantes de mise en page.
<p>Comme la plupart des livres … à propos du Magicien d’Oz</li>\n</ul>\n
templateToutes sortes de données analysées par le modèle. Des choses comme la configuration d’Eleventy, la configuration du moteur de rendu pour le markdown, et beaucoup de choses sur lesquelles nous ne devrions probablement pas nous baser.

Implémentation : Comment un tag devient une collection

getTaggedCollectionsData() est la fonction qui transforme des tags en collections.

146async getTaggedCollectionsData() {
147  let collections = {};
148  collections.all = this.createTemplateMapCopy(
149    this.collection.getAllSorted()
150  );
151  debug(`Collection: collections.all size: ${collections.all.length}`);
152
153  let tags = this.getAllTags();
154  for (let tag of tags) {
155    collections[tag] = this.createTemplateMapCopy(
156      this.collection.getFilteredByTag(tag)
157    );
158    debug(`Collection: collections.${tag} size: ${collections[tag].length}`);
159  }
160  return collections;
161}

getTaggedCollectionsData() est appelée dans TemplateMap.cache() qui est l’endroit ou Eleventy génère les collections.

Les collections sur mesure

Outre les collections créées à partir de tags, vous pouvez utiliser la fonction addCollection() dans votre fichier de configuration .eleventy.js pour créer vos propres collections.

Par exemple, voici comment créer une collection nommée articles constituée de pages générées à partir de modèles présents dans le dossier src/articles/ :

eleventyConfig.addCollection("articles",
  collection => collection
    .getAllSorted()
    .filter(item => item.url
                 && ! item.inputPath.includes('index.njk')
                 && item.inputPath.startsWith('./src/articles/')))

La fonction addCollection() prend deux paramètres1 :

  • le nom de la collection (une chaîne de caractères)
  • une fonction qui prend une collection en paramètre.

qui construit la collection au nom de la collection. La fonction qui construit la collection est elle-même appelée plus tard dans getUserConfigCollectionsData().

  ```js
  addCollection(name, callback) {
    name = this.getNamespacedName(name);

    if (this.collections[name]) {
      throw new UserConfigError(
        `config.addCollection(${name}) already exists. Try a different name for your collection.`
      );
    }

    this.collections[name] = callback;
  }
  ```

Vous pourriez penser que le paramètre collection est un tableau d’objets de modèle comme l’objet collections basé sur les tags. Ce paramètre est en fait une instance d’une TemplateCollection, qui dérive de Sortable, et ressemble à ceci :

{
  "items": [
    { ... },
    . . .
    { ... }
  ],
  "sortFunctionStringMap": { ... },
  "sortAscending": true,
  "sortNumeric": false
}

La propriété items est un tableau de tous les objets de modèle. C’est la même chose que collections.all. Vous ne voulez pas accéder aux éléments directement en écrivant : collection.item[n]. Utilisez plutôt les méthodes suivantes pour accéder aux éléments.

collection api methods
MéthodeDescription
getAll()Récupérer tous les éléments dans un ordre spécifique.
getAllSorted()Récupérer tous les éléments dans l’ordre.
getFilteredByTag(tagName)Récupérer tous les éléments qui possèdent un tag spécifique.
getFilteredByGlob(glob)Récupérer tous les éléments dont l’ inputPath correspond à un ou plusieurs patterns globaux.

Les éléments sont presque les mêmes que ceux des collections basées sur des tags, à la différence près que dans les collections basées sur des tags, les éléments ont une propriété templateContent. Dans les collections créées avec la fonction addCollection(), les éléments ont une propriété _pages. Je ne saurais dire pourquoi.

Vous pouvez utiliser addCollection() pour créer des collections de pages. Depuis Eleventy 0.5.3, vous pouvez l’utiliser pour créer des collections ou des objets de votre choix.

Par exemple, voici comment vous créeriez une collection constituée d’un tableau de toutes les catégories :

module.exports = function(collection) {
  let catSet = new Set()

  collection.getAllSorted().forEach(item =>
        typeof item.data.category === "string"
    &&  catSet.add(item.data.category))

  return [...catSet]
};

Implémentation : Comment sont construites les collections sur mesure

getUserConfigCollectionsData() est la fonction qui appelle ce qui est retourné par la fonction addCollection().

async getUserConfigCollectionsData() {
  let collections = {};
  let configCollections =
    this.configCollections || eleventyConfig.getCollections();
  for (let name in configCollections) {
    let ret = configCollections[name](this.collection);

    // work with arrays and strings returned from UserConfig.addCollection
    if (
      Array.isArray(ret) &&
      ret.length &&
      ret[0].inputPath &&
      ret[0].outputPath
    ) {
      collections[name] = this.createTemplateMapCopy(ret);
    } else {
      collections[name] = ret;
    }

    debug(
      `Collection: collections.${name} size: ${collections[name].length}`
    );
  }
  return collections;
}

getUserConfigCollectionsData() est appelé dans TemplateMap.cache() qui est l’endroit où Eleventy construit les collections.


  1. addCollection() ne fait rien d’autre qu’associer la fonction