Руководство по началу работы с минимумом

Каждый раз, когда я открываю сайт с документацией Eleventy, меня охватывает желание расплакаться или сменить работу! Поэтому я решил создать небольшой веб-сайт, на котором нет абсолютно ничего, кроме самого минимума, и оставить его в качестве справочного материала, чтобы в следующий раз, когда я буду рассматривать Eleventy, мне не нужно было проходить через их ценные — но болезненные — начинайте!

Финальный проект на StackBlitz

План состоит в том, чтобы охватить следующее:

  • Настройка одиннадцати
  • Одиннадцать папок
    _data папка
    _includes папка
  • Передний вопрос
  • Несколько файлов из коллекции
  • Несколько файлов из массива
  • Особенности жидкости
  • Включаемые файлы Liquid
    Передача переменных
    Области макета
  • Бонус: сначала удалите папку
  • Хостинг на страницах GitHub

Минимум

Цель состоит в том, чтобы охватить основы, после чего становится легче находить детали в документации.

  • Жидкость, с использованием HTML-расширений
  • Установить только глобально
  • Две конфигурации, одна для разработки и одна для публикации.
  • Развернуть только папку dist, без пайплайнов, без действий
  • Использовать по умолчанию _data и _includes
  • Нет плагинов

Я также развернусь на Github Pages, чтобы напомнить себе, насколько это просто; их документация заставляет вас поверить, что это военная миссия!

Настройка одиннадцати

1. Установите Eleventy глобально

npm install -g @11ty/eleventy

2. Создайте папку для проекта и npm init для дальнейшего использования. Это полезно, если мы хотим сделать локальную установку, или добавить другие пакеты, или просто сохранить ярлык скриптов.

3. Создайте файл конфигурации .eleventy.js, чтобы изменить исходный каталог (чтобы все было аккуратно), и единственный действительно ценный параметр — addPassthroughCopy:

// .eleventy.js
module.exports = function (eleventyConfig) {
  // this is a must, pass through your assets
  eleventyConfig.addPassthroughCopy("src/assets");
     return {
	 dir: {
	    input: "src"
	    // the default output is _site
	 }
    }
};

4. Создайте папку src и добавьте свой первый HTML

<!DOCTYPE html>
<html>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

5. Запустите одну из следующих команд:

  • eleventy создает сайт в папке _site
  • eleventy --serve создает сайт, следит за изменениями и запускает локальный сервер в localhost:8080
  • eleventy --watch генерирует сайт, следит за изменениями, но не запускает сервер, вам решать запустить сервер, который обслуживает папку _site
  • eleventy --config=somethingelse использует другой файл конфигурации для создания сайта.

6. Создайте новый файл: .distconfig.js для создания в другой папке

// first get the dev config in
const devConfig = require("./.eleventy.js");
module.exports = function (eleventyConfig) {
  // pass everything from config
  const config = devConfig(eleventyConfig);
  // set different output, you can deep clone first but it's too much work
  return {
    dir: {
      input: config.dir.input, 
      output: "dist"
    }
  };
};

Запустите eleventy --config:.distconfig.js, результат будет в папке dist. Разверните это!

Вот и все. Это самый минимум. Но не совсем полезно не так ли? Давайте добавим наши сценарии быстрого доступа в packages.json и продолжим.

// packages.json
{
  "scripts": {
    "start": "eleventy --serve",
    "watch": "eleventy --watch",
    "build": "eleventy --config=.distconfig.js"
  }
}

Одиннадцать папок

Наиболее важны две папки внутри src: _data и _includes. Содержимое не обрабатывается, поэтому оно может содержать все данные, макеты, шорткоды и плагины.

_data папка

Имя файла — это имя объекта JavaScript, начинающееся с something.json.

// src/_data/something.json
{
  "name": "orange"
}

Это используется в HTML следующим образом:

<div>
<!-- in html, this outputs: orange -->
{{ something.name }}
</div>

Если это массив, things.json:

// src/_data/things.json
[
  {
    "name": "orange"
  },
  {
    "name": "purple"
  }
]

В HTML:

<div>
<!-- in html, any html, this outputs: orange, purple -->
{{ things[0].name }}, {{ things[1].name }}
</div>
<!-- for loop in liquid -->
<ul>
  {% for thing in things %}
  <li>{{ thing.name }}</li>
  {% endfor %}
</ul>

Если это ключ-значение, fewthings.json:

// src/_data/fewthings.json
{
  "orange": "sunny orange",
  "purple": "dark purple"
}

В HTML:

<p>
  <!-- this outputs: sunny orange, dark purple -->
  {{ fewthings.orange }}, {{ fewthings.purple }}
</p>
<!-- for loop in liquid, with key-value -->
<ul>
  {% for thing in fewthings %}
  <!-- first element is key, second is value -->
  <li>{{ thing[0] }}: {{ thing[1] }}</li>
  {% endfor %}
</ul>

_Includes папка

_includes — это место, где создаются шаблоны. Начните с базового HTML-шаблона: base.html. Обратите внимание, что до сих пор нам не нужно было создавать никаких специальных расширений. Единственная переменная шаблона, которая работает «из коробки», — это {{content}}. В расширении HTML фильтр safe не нужен и не будет работать.

<!-- src/_includes/base.html -->
<!DOCTYPE html>
<html>
  <head>
    <!-- title is a variable that needs to be set in child page -->
    <title>{{ title }} | Base 11ty Template</title>
  </head>
  <body>
    <h1>Hello 11ty</h1>
    <!-- here is the template literal that passes the content  -->
    {{ content }}
  </body>
</html>

Передний вопрос

Давайте создадим наш первый файл с минимумом вступительной части:

<!-- src/index.html -->
---
# must be directly under _includes folder
layout: "base.html"
# title is optional
title: "a new title"
---
<h2>The base page using base html</h2>

Чтобы включить содержимое другого файла:

{% include './filelocation/file.html' %}

Создать дополнительный макет так же просто, как создать первый макет, все данные передаются вверх:

<!-- src/_includes/color.html -->
---
layout: base.html
---
<div>
<!-- the color variable is fed from pages using this template -->
	Here is the details of {{ color }}
</div>
{{ content }}

Снаружи создадим папку colors и пару html файлов:

<!-- src/colors/orange.html-->
---
# use child layout
layout: color.html
# pass color to first layout
color: orange
# pass title to parent layout
title: Orange
---
<h1>{{ color }} page</h1>

Несколько файлов из tags с использованием collections

collection в Eleventy — это группа похожих страниц, сходство основано на свойстве tags. Это позволяет нам перечислять похожие страницы, каждая item имеет собственное свойство data.

<!-- src/colors/orange.html, similar purple.html -->
---
layout: color.html
color: orange
title: Orange
tags: colors
---
<h1>{{ color }} page</h1>

Перечисление их в любом месте, здесь они перечислены в макете color.html

<!-- src/_includes/color.html -->
<h5>List of all colors</h5>
<ul>
	<!-- 'collections' is provided by 11ty, 
		'colors' is the tags property,
		'data' is provided by 11ty, -->
  {% for item in collections.colors %}
	  <li>{{ item.data.color }}</li>
  {% endfor %}
</ul>

Одиннадцать предоставили данные

Мы можем использовать page.url для сравнения с collections[item].url для выделения текущего элемента в списке.

<!-- src/_includes/color.html -->
<ul>
  {% for item in collections.colors %}
	<!-- inline if condition for page.url and item.url, both provided by 11ty -->
  <li {% if page.url == item.url %}class="selected"{% endif %}>
    <a href="{{item.url}}">{{ item.data.color }}</a>
  </li>
  {% endfor %}
</ul>

Вот как вы перечисляете страницы с одним и тем же tags, но он слишком фрагментирован. Лучший способ — позволить Eleventy перебирать данные array и создавать соответствующие страницы.

Несколько файлов из массива с использованием pagination

Чтобы сгенерировать несколько файлов HTML из массива в папке _data, например, things.json:

<!-- src/loop.html, use front matter to create multiple files -->
---
layout: "base.html"
pagination:
  data: things
  # size 1 to create a page per item
  size: 1
  # alias it to use its props
  alias: thing
---
{{ thing.name }}

Это генерирует

/_site/loop/index.html (индекс 0 удален из URL)

/_site/loop/1/index.html

Чтобы изменить имена файлов на собственные имена, мы используем permalink, обратите внимание на символы /, он создает подпапку для index.html и, таким образом, удобный URL-адрес.

<!-- src/loop.html -->
---
layout: "base.html"
pagination:
  data: things
  size: 1
  alias: thing
# use permalink to fix the file names, use slugify filter to make name slug-ish
permalink: "loop/{{ thing.name | slugify }}/"
---
{{ thing.name }}

Это создаст

/_site/loop/orange/index.html

/_site/loop/purple/index.html

Если бы имя было Liberty Statue, фильтр slugify создал бы: liberty-statue

Большой. Теперь, чтобы вернуть свойства в базовый шаблон, мы используем eleventyComputed в начале текста, обратите внимание на формат значения свойства:

<!-- src/loop.html -->
---
layout: "base.html"
pagination:
  data: things
  size: 1
  alias: thing
permalink: "loop/{{ thing.name | slug }}/"
# pass back the title to base template: use quotations
eleventyComputed:
  title: "{{thing.name}}"
---
{{ thing.name }}

Их перечисление так же просто, как перебор массива, к сожалению, сопоставление текущей страницы с одним из элементов требует небольшой работы. Eleventy предоставляет объект pagination, который доступен на страницах, которые его используют, одно свойство — hrefs, которое мы можем использовать для сравнения с page.url. forloop.index0 — это синтаксис Liquid для индекса элемента в массиве, начинающемся с нуля.

<ul>
  {% for thing in things %}
    <!-- pagination.hrefs is provided by 11ty
         forloop.index0 is liquid syntax for zero-based index -->
    <li {% if page.url == pagination.hrefs[forloop.index0] %}class="selected"{% endif %}>
      <a href="/loop/{{thing.name | slugify }}">{{ thing.name }}</a>
    </li>
  {% endfor %}
</ul>

Особенности жидкости

В Liquid JS очень удобно следующее:

  • присвоить имя переменной и использовать его

{% assign something: 'pretty' %}{{ something }}

  • чтобы открыть жидкую область с несколькими линиями
{% liquid
	assign var = value | filter
	# other liquid statements
%}

Liquid включают файлы

Чаще всего я хочу совместить две функции: централизовать массив под _data и иметь свободу написания HTML. Для этого мы используем включаемые файлы Liquid.

Чтобы включить другой файл как есть, другой файл HTML, позвольте мне начать с примера, имеющего файлы данных HTML в папке _data:

<!-- /_data/things/orange.html, and a similar one purple.html -->
<h4>Orange</h4>
<p>
  This is a rich HTML content file, that has access to liquid template variables
</p>

В файле loop сделайте включение:

<!-- src/loop.html -->
<!-- include _data/thingname.html as it is -->
{% include './_data/things/{{thing.name | slugify }}.html' %}

Примечание: мы должны создать файлы вручную и убедиться, что имя файла равно выходу фильтра slugify. Но лучший способ — создать новое свойство в нашем things.json с slug и вместо этого использовать его везде.

Передача переменных

Мы можем передавать переменные и использовать их в HTML в Liquid:

<!-- src/loop.html -->
---
layout: "base.html"
pagination:
  data: things
  size: 1
  alias: thing
permalink: "loop/{{ thing.name | slugify }}/"
eleventyComputed:
  title: "{{thing.name}}"
---
<!-- pass a property -->
{% include './_data/things/{{thing.name | slugify }}.html', theme: 'dark' %}

Затем используйте его:

<!-- src/_data/things/orange.html -->
<h4>Orange</h4>
<p>
  {{ theme }}
</p>

Жидкие области макета

Блоки макета Liquid не поддерживаются, однако есть поддержка переменных шаблона. Мы можем создать условие на наших HTML-страницах:

<!-- src/_data/things/orange.html -->
{% case region %}
  {% when "header" %}
     Header of orange
  {% when "content" %}
     The content region of orange, and the theme is {{ theme }}
{% endcase %}

И используем его в нашем цикле

<!-- src/loop.html -->
---
layout: "base.html"
pagination:
  data: things
  size: 1
  alias: thing
permalink: "loop/{{ thing.name | slugify }}/"
eleventyComputed:
  title: "{{thing.name}}"
---
<!-- include regions -->
<h4>{{ thing.name }}</h4>
<!-- liquid island to assign a _filepath variable -->
{% liquid 
  assign _slug = thing.name | slugify
	assign _filepath = './_data/things/' | append: _slug  | append: '.html'
%}
<article>
  <header>
    {% include _filepath', region: 'header' %}
  </header>
  <div>
		<!-- passing extra params are okay -->
    {% include _filepath, region: 'content', theme: 'dark' %}
  </div>
</article>

Мне просто нужно напомнить себе, что это можно сделать немного дальше, создав дополнительные регионы для использования в другом месте. Например, если у меня был регион excerpt, я могу отобразить его на главной странице.

<!-- src/_data/things/orange.html -->
{% case region %}
	{% when "excerpt" %}
		Short excerpt of Orange
  {% when "header" %}
     Header of orange
  {% when "content" %}
     The content region of orange, and the theme is {{ theme }}
{% endcase %}

В петле:

{% for thing in things %}
 
  <li>
    ...
    add excerpt region
    <div>
    {% include './_data/things/{{thing.name | slugify }}.html', region: 'excerpt' %}
    </div>
  </li>
{% endfor %}

Итак, это было Начало работы. Более глубокие вещи легче найти, когда мы научимся ходить. Некоторые из вещей, которые нужно искать:

  • Одиннадцать конфигураций, специально для перехода на Nunjucks.
  • Шаблоны Nunjucks, расширенные шаблоны и области шаблонов
  • Одиннадцать Данные, полученные из макетов
  • Одиннадцать шорткодов, фильтров и плагинов

Бонус: сначала удалите папки

Бонусом является удаление папок _site и dist перед запуском и сборкой, вы можете найти другие решения в Интернете, но вот простой минимум в файлах конфигурации:

// .eleventy.js
// get fs from Node
const fs = require('fs');
module.exports = function (eleventyConfig) {
	
	// rm sync _site folder, recursively
	fs.rmSync('./_site', {recursive: true, force: true});
	
	// ... 
};
// .distconfig.js
const fs = require('fs');
module.exports = function (eleventyConfig) {
	// rm sync dist folder
	fs.rmSync('./dist', {recursive: true, force: true});
	// remember: this will also remove _site
	const config = devConfig(eleventyConfig);
	
  // ...
};

Разместим на GitHub Pages

Хостинг на страницах GitHub

  1. Соберите проект: npm run build
  2. Поместите проект в репозиторий GitHub (есть несколько способов сделать это, ни один из них не является прямым, если у вас есть визуальный интерфейс, такой как VSCode, это немного упрощает задачу). Игнорировать папку _site, но разрешить папку dist. В минимальной настройке нет папки node_modules.
  3. В репозитории GitHub перейдите в раздел Настройки › Страницы.
  4. В разделе Сборка и развертывание выберите Действия Github. Вы перейдете на вновь созданную страницу .github/workflows/pages.yml.
  5. Прокрутите вниз до строки 39 (приблизительно): jobs>deploy>steps>with>path и измените ее на ./dist.
  6. Совершить

Вы, вероятно, захотите получить это локально для будущих коммитов.

Подождите 10 минут или чуть больше, когда вы вернетесь в Настройки › Страницы, новый URL будет отображаться сверху. Скорее всего, это будет

https://[username].github.io/[repositoryname]

Если вы настроите собственный домен, это будет

https://[customdomain]/[repositoryname]

Если имя вашего репозитория [username].github.io, URL-адрес будет таким:

https://[customedomain]

Примечание: вам нужно настроить пользовательский домен для [username].github.io только один раз, все новые репозитории могут автоматически обслуживаться за пределами вашего личного домена.

Для личного домена или поддомена в диспетчере DNS настройте:

CNAME record: 
- name: www [or subdomain], 
- value: [username].github.io

Чтобы добавить домен вершины (www), также добавьте:

A Record:  
- name: @ (or domain.com)
- value: 185.199.108.153

Итак, вот наш проект на GitHub и размещен на Страницах.

Одиннадцать, демистифицировано.

РЕСУРСЫ

Читайте лучше в Sekrab Garage