@anydigital/eleventy-bricks 0.27.0 → 0.28.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +390 -958
- package/package.json +1 -1
- package/src/eleventy.config.js +47 -21
- package/src/filters/strip_tag.js +41 -0
- package/src/filters/strip_tag.test.js +74 -0
- package/src/index.js +7 -3
- package/examples/section-filter.md +0 -96
- package/src/index.cjs +0 -51
- /package/src/{transforms → processors}/autoLinkFavicons.js +0 -0
- /package/src/{transforms → processors}/autoLinkFavicons.test.js +0 -0
- /package/src/{transforms → processors}/markdown.js +0 -0
- /package/src/{transforms → processors}/markdown.test.js +0 -0
package/README.md
CHANGED
|
@@ -2,668 +2,309 @@
|
|
|
2
2
|
|
|
3
3
|
A collection of helpful utilities and filters for Eleventy (11ty).
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
```
|
|
7
|
+
```sh
|
|
8
8
|
npm install @anydigital/eleventy-bricks
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
You can use this library in two ways:
|
|
11
|
+
Then choose one of the following options:
|
|
14
12
|
|
|
15
|
-
### Option
|
|
13
|
+
### Option A. Starting 11ty from scratch?
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
Consider symlinking entire `eleventy.config.js`:
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
import eleventyBricks from "@anydigital/eleventy-bricks";
|
|
17
|
+
```sh
|
|
18
|
+
ln -s ./node_modules/@anydigital/eleventy-bricks/src/eleventy.config.js
|
|
19
|
+
```
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
eleventyConfig.addPlugin(eleventyBricks, {
|
|
26
|
-
mdAutoRawTags: true,
|
|
27
|
-
mdAutoNl2br: true,
|
|
28
|
-
autoLinkFavicons: true,
|
|
29
|
-
siteData: true,
|
|
30
|
-
filters: ["attr_set", "attr_includes", "merge", "remove_tag", "if", "attr_concat", "section", "fetch"],
|
|
31
|
-
});
|
|
21
|
+
[Learn more below](#symlink-config) and see https://github.com/anydigital/sveleven as a living example.
|
|
32
22
|
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
```
|
|
23
|
+
### Option B. Adding to existing 11ty site?
|
|
36
24
|
|
|
37
|
-
|
|
25
|
+
Use as a plugin in `eleventy.config.js` (recommended):
|
|
38
26
|
|
|
39
|
-
```
|
|
40
|
-
|
|
27
|
+
```js
|
|
28
|
+
import eleventyBricksPlugin from "@anydigital/eleventy-bricks";
|
|
41
29
|
|
|
42
|
-
|
|
43
|
-
eleventyConfig.addPlugin(
|
|
30
|
+
export default function (eleventyConfig) {
|
|
31
|
+
eleventyConfig.addPlugin(eleventyBricksPlugin, {
|
|
44
32
|
mdAutoRawTags: true,
|
|
45
33
|
mdAutoNl2br: true,
|
|
46
34
|
autoLinkFavicons: true,
|
|
47
35
|
siteData: true,
|
|
48
|
-
filters: ["attr_set", "
|
|
36
|
+
filters: ["attr_set", "attr_concat", ...],
|
|
49
37
|
});
|
|
50
|
-
|
|
51
|
-
// Your other configuration...
|
|
52
|
-
};
|
|
38
|
+
}
|
|
53
39
|
```
|
|
54
40
|
|
|
55
|
-
>
|
|
41
|
+
<details><summary>
|
|
56
42
|
|
|
57
|
-
### Option
|
|
43
|
+
### Option C. Individual imports
|
|
58
44
|
|
|
59
|
-
|
|
45
|
+
</summary>
|
|
60
46
|
|
|
61
|
-
|
|
47
|
+
For advanced usage, import individual components only in `eleventy.config.js`:
|
|
62
48
|
|
|
63
|
-
```
|
|
64
|
-
import {
|
|
65
|
-
mdAutoRawTags,
|
|
66
|
-
mdAutoNl2br,
|
|
67
|
-
autoLinkFavicons,
|
|
68
|
-
attrSetFilter,
|
|
69
|
-
attrIncludesFilter,
|
|
70
|
-
mergeFilter,
|
|
71
|
-
removeTagFilter,
|
|
72
|
-
ifFilter,
|
|
73
|
-
attrConcatFilter,
|
|
74
|
-
sectionFilter,
|
|
75
|
-
fetchFilter,
|
|
76
|
-
siteData,
|
|
77
|
-
} from "@anydigital/eleventy-bricks";
|
|
49
|
+
```js
|
|
50
|
+
import { siteData, mdAutoRawTags, mdAutoNl2br, autoLinkFavicons, attrSetFilter, attrConcatFilter, ... } from "@anydigital/eleventy-bricks";
|
|
78
51
|
|
|
79
52
|
export default function (eleventyConfig) {
|
|
53
|
+
siteData(eleventyConfig);
|
|
80
54
|
mdAutoRawTags(eleventyConfig);
|
|
81
55
|
mdAutoNl2br(eleventyConfig);
|
|
82
56
|
autoLinkFavicons(eleventyConfig);
|
|
83
57
|
attrSetFilter(eleventyConfig);
|
|
84
|
-
attrIncludesFilter(eleventyConfig);
|
|
85
|
-
mergeFilter(eleventyConfig);
|
|
86
|
-
removeTagFilter(eleventyConfig);
|
|
87
|
-
ifFilter(eleventyConfig);
|
|
88
58
|
attrConcatFilter(eleventyConfig);
|
|
89
|
-
|
|
90
|
-
// fetchFilter is only available if @11ty/eleventy-fetch is installed
|
|
91
|
-
if (fetchFilter) {
|
|
92
|
-
fetchFilter(eleventyConfig);
|
|
93
|
-
}
|
|
94
|
-
siteData(eleventyConfig);
|
|
95
|
-
|
|
96
|
-
// Your other configuration...
|
|
59
|
+
...
|
|
97
60
|
}
|
|
98
61
|
```
|
|
99
62
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```javascript
|
|
103
|
-
const {
|
|
104
|
-
mdAutoRawTags,
|
|
105
|
-
mdAutoNl2br,
|
|
106
|
-
autoLinkFavicons,
|
|
107
|
-
attrSetFilter,
|
|
108
|
-
attrIncludesFilter,
|
|
109
|
-
mergeFilter,
|
|
110
|
-
removeTagFilter,
|
|
111
|
-
ifFilter,
|
|
112
|
-
attrConcatFilter,
|
|
113
|
-
sectionFilter,
|
|
114
|
-
fetchFilter,
|
|
115
|
-
siteData,
|
|
116
|
-
} = require("@anydigital/eleventy-bricks");
|
|
117
|
-
|
|
118
|
-
module.exports = async function (eleventyConfig) {
|
|
119
|
-
await mdAutoRawTags(eleventyConfig);
|
|
120
|
-
await mdAutoNl2br(eleventyConfig);
|
|
121
|
-
await autoLinkFavicons(eleventyConfig);
|
|
122
|
-
await attrSetFilter(eleventyConfig);
|
|
123
|
-
await attrIncludesFilter(eleventyConfig);
|
|
124
|
-
await mergeFilter(eleventyConfig);
|
|
125
|
-
await removeTagFilter(eleventyConfig);
|
|
126
|
-
await ifFilter(eleventyConfig);
|
|
127
|
-
await attrConcatFilter(eleventyConfig);
|
|
128
|
-
await sectionFilter(eleventyConfig);
|
|
129
|
-
// fetchFilter is only available if @11ty/eleventy-fetch is installed
|
|
130
|
-
if (fetchFilter) {
|
|
131
|
-
await fetchFilter(eleventyConfig);
|
|
132
|
-
}
|
|
133
|
-
await siteData(eleventyConfig);
|
|
134
|
-
|
|
135
|
-
// Your other configuration...
|
|
136
|
-
};
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
> **Note:** When using CommonJS with individual helpers, the config function must be `async` and each helper must be `await`ed, as the CommonJS wrapper uses dynamic imports internally.
|
|
140
|
-
|
|
141
|
-
## Configuration Options
|
|
142
|
-
|
|
143
|
-
When using the plugin (Option 1), you can configure which helpers to enable:
|
|
144
|
-
|
|
145
|
-
| Option | Type | Default | Description |
|
|
146
|
-
| ------------------ | --------------- | ------- | ---------------------------------------------------------------- |
|
|
147
|
-
| `mdAutoRawTags` | boolean | `false` | Enable the mdAutoRawTags preprocessor for Markdown files |
|
|
148
|
-
| `mdAutoNl2br` | boolean | `false` | Enable the mdAutoNl2br preprocessor to convert \n to `<br>` tags |
|
|
149
|
-
| `autoLinkFavicons` | boolean | `false` | Enable the autoLinkFavicons transform to add favicons to links |
|
|
150
|
-
| `siteData` | boolean | `false` | Enable site.year and site.prod global data |
|
|
151
|
-
| `filters` | array of string | `[]` | Array of filter names to enable (see Available Filters section) |
|
|
152
|
-
|
|
153
|
-
**Available filter names for the `filters` array:**
|
|
154
|
-
|
|
155
|
-
- `'attr_set'` - Override object attributes
|
|
156
|
-
- `'attr_includes'` - Filter collections by attribute values
|
|
157
|
-
- `'merge'` - Merge arrays or objects
|
|
158
|
-
- `'remove_tag'` - Remove HTML elements from content
|
|
159
|
-
- `'if'` - Inline conditional/ternary operator
|
|
160
|
-
- `'attr_concat'` - Concatenate values to an attribute array
|
|
161
|
-
- `'section'` - Extract named sections from content marked with HTML comments
|
|
162
|
-
- `'fetch'` - Fetch remote URLs or local files (requires `@11ty/eleventy-fetch`)
|
|
163
|
-
|
|
164
|
-
**Example:**
|
|
165
|
-
|
|
166
|
-
```javascript
|
|
167
|
-
eleventyConfig.addPlugin(eleventyBricks, {
|
|
168
|
-
mdAutoRawTags: true,
|
|
169
|
-
mdAutoNl2br: true,
|
|
170
|
-
autoLinkFavicons: true,
|
|
171
|
-
siteData: true,
|
|
172
|
-
filters: ["attr_set", "attr_includes", "merge", "remove_tag", "if", "attr_concat", "section", "fetch"],
|
|
173
|
-
});
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Additional Exports
|
|
177
|
-
|
|
178
|
-
The plugin also exports the following utility functions for advanced usage:
|
|
179
|
-
|
|
180
|
-
- `transformAutoRaw(content)`: The transform function used by `mdAutoRawTags` preprocessor. Can be used programmatically to wrap Nunjucks syntax with raw tags.
|
|
181
|
-
- `transformNl2br(content)`: The transform function used by `mdAutoNl2br` preprocessor. Can be used programmatically to convert `\n` sequences to `<br>` tags.
|
|
182
|
-
- `isPlainUrlText(linkText, domain)`: Helper function that checks if link text looks like a plain URL or domain.
|
|
183
|
-
- `cleanLinkText(linkText, domain)`: Helper function that cleans link text by removing protocol, domain, and leading slash.
|
|
184
|
-
- `buildFaviconLink(attrs, domain, text)`: Helper function that builds HTML for a link with favicon.
|
|
185
|
-
- `transformLink(match, attrs, url, linkText)`: The transform function used by `autoLinkFavicons` that transforms a single link to include a favicon.
|
|
186
|
-
- `replaceLinksInHtml(content, transformer)`: Helper function that replaces all anchor links in HTML content with transformed versions.
|
|
187
|
-
- `attrIncludes(collection, attrName, targetValue)`: The core logic for filtering collection items by checking if an attribute array includes a target value. Can be used programmatically to filter collections.
|
|
188
|
-
- `merge(first, ...rest)`: The core merge function used by the `merge` filter. Can be used programmatically to merge arrays or objects.
|
|
189
|
-
- `removeTag(html, tagName)`: The core function used by the `remove_tag` filter. Can be used programmatically to remove HTML tags from content.
|
|
190
|
-
- `iff(trueValue, condition, falseValue)`: The core conditional function used by the `if` filter. Can be used programmatically as a ternary operator.
|
|
191
|
-
- `attrConcat(obj, attr, values)`: The core function used by the `attr_concat` filter. Can be used programmatically to concatenate values to an attribute array.
|
|
192
|
-
- `attrSet(obj, key, value)`: The core function used by the `attr_set` filter. Can be used programmatically to override object attributes.
|
|
193
|
-
- `section(content, sectionName)`: The core function used by the `section` filter. Can be used programmatically to extract named sections from content.
|
|
194
|
-
|
|
195
|
-
<!--section:11ty-->
|
|
196
|
-
|
|
197
|
-
## Tricks from [Eleventy Bricks](https://github.com/anydigital/eleventy-bricks) {#eleventy-bricks}
|
|
198
|
-
|
|
199
|
-
### Filters
|
|
200
|
-
|
|
201
|
-
| Input | Nunjucks | Liquid <hr> |
|
|
202
|
-
| ---------: | ------------------------------------------------------------------------------ | ---------------------------------------------------- |
|
|
203
|
-
| {.divider} | Logical |
|
|
204
|
-
| `ANY \| ` | `default(VALUE)` <br>= `d(...)` | `default: VALUE` |
|
|
205
|
-
| `ANY \|` | [`if(TEST, OP, VALUE)`](#if) <sub>currently only `if(TEST)`</sub> | [`if: TEST, OP, VALUE`](#if) |
|
|
206
|
-
| {.divider} | On objects |
|
|
207
|
-
| `OBJ \|` | [`merge(OBJ2)`](#merge) | [`merge: OBJ2`](#merge) |
|
|
208
|
-
| {.divider} | On object attributes |
|
|
209
|
-
| `OBJ \|` | `selectattr(BOOL_ATTR)` | `where: ATTR, VALUE` |
|
|
210
|
-
| `OBJ \|` | `rejectattr(BOOL_ATTR)` | N/A |
|
|
211
|
-
| `OBJ \|` | [`attr_includes(ARRAY_ATTR, VALUE)`](#attr_includes) <sub>was `where_in`</sub> | [`attr_includes: ARRAY_ATTR, VALUE`](#attr_includes) |
|
|
212
|
-
| `OBJ \|` | [`attr_set(ATTR, VALUE)`](#attr_set) <sub>was `attr`</sub> | [`attr_set: ATTR, VALUE`](#attr_set) |
|
|
213
|
-
| `OBJ \|` | [`attr_concat(ARRAY_ATTR, ARRAY2)`](#attr_concat) | [`attr_concat: ARRAY_ATTR, ARRAY2`](#attr_concat) |
|
|
214
|
-
| {.divider} | Textual |
|
|
215
|
-
| `HTML \|` | `striptags` | `strip_html` |
|
|
216
|
-
| `HTML \|` | [`remove_tag(TAG)`](#remove_tag) | [`remove_tag: TAG`](#remove_tag) |
|
|
217
|
-
| `HTML \|` | [`section(NAME)`](#section) | [`section: NAME`](#section) |
|
|
218
|
-
| `STR \|` | `remove: STR2` | `remove: STR2` |
|
|
219
|
-
| {.divider} | Other |
|
|
220
|
-
| `URL \|` | [`fetch`](#fetch) | [`fetch`](#fetch) |
|
|
221
|
-
|
|
222
|
-
Ref:
|
|
223
|
-
|
|
224
|
-
- https://mozilla.github.io/nunjucks/templating.html#builtin-filters
|
|
225
|
-
- https://shopify.github.io/liquid/
|
|
226
|
-
|
|
227
|
-
#### `attr_set`
|
|
228
|
-
|
|
229
|
-
A filter that creates a new object with an overridden attribute value. This is useful for modifying data objects in templates without mutating the original.
|
|
230
|
-
|
|
231
|
-
**Why use this?**
|
|
232
|
-
|
|
233
|
-
When working with Eleventy data, you sometimes need to modify an object's properties for a specific use case. The `attr_set` filter provides a clean way to create a modified copy of an object without affecting the original.
|
|
63
|
+
</details>
|
|
234
64
|
|
|
235
|
-
|
|
65
|
+
## Command Line Tools
|
|
236
66
|
|
|
237
|
-
|
|
67
|
+
<!--section:npm-h3-->
|
|
238
68
|
|
|
239
|
-
|
|
240
|
-
import { attrSetFilter } from "@anydigital/eleventy-bricks";
|
|
69
|
+
### 🥷 Reusable 11ty npm scripts <small>via npm workspace</small> <br><sub>from https://github.com/anydigital/eleventy-bricks</sub>
|
|
241
70
|
|
|
242
|
-
|
|
243
|
-
attrSetFilter(eleventyConfig);
|
|
244
|
-
// Or use as plugin:
|
|
245
|
-
// eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr_set'] });
|
|
246
|
-
}
|
|
247
|
-
```
|
|
71
|
+
This package provides a pre-configured `do` folder setup that helps organize your development workflow using npm workspaces. The `do` folder contains scripts for building and running your Eleventy project.
|
|
248
72
|
|
|
249
|
-
|
|
73
|
+
**Installation:**
|
|
250
74
|
|
|
251
|
-
|
|
252
|
-
{# Create a modified version of a page object #}
|
|
253
|
-
{% set modifiedPage = page | attr_set('title', 'New Title') %}
|
|
75
|
+
1. Install https://github.com/anydigital/eleventy-bricks to reuse pre-defined 11ty scripts from there:
|
|
254
76
|
|
|
255
|
-
|
|
256
|
-
|
|
77
|
+
```sh
|
|
78
|
+
npm install @anydigital/eleventy-bricks
|
|
257
79
|
```
|
|
258
80
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
- `obj`: The object to modify
|
|
262
|
-
- `key`: The attribute name to set (string)
|
|
263
|
-
- `value`: The value to set for the attribute (any type)
|
|
264
|
-
|
|
265
|
-
**Returns:**
|
|
266
|
-
|
|
267
|
-
A new object with the specified attribute set to the given value. The original object is not modified.
|
|
268
|
-
|
|
269
|
-
**Features:**
|
|
270
|
-
|
|
271
|
-
- Non-mutating: Creates a new object, leaving the original unchanged
|
|
272
|
-
- Works with any object type
|
|
273
|
-
- Supports any attribute name and value type
|
|
274
|
-
- Can be chained with other filters
|
|
275
|
-
|
|
276
|
-
**Examples:**
|
|
277
|
-
|
|
278
|
-
```njk
|
|
279
|
-
{# Override a single attribute #}
|
|
280
|
-
{% set updatedPost = post | attr_set('featured', true) %}
|
|
281
|
-
|
|
282
|
-
{# Chain multiple attr_set filters #}
|
|
283
|
-
{% set modifiedPost = post
|
|
284
|
-
| attr_set('category', 'blog')
|
|
285
|
-
| attr_set('priority', 1)
|
|
286
|
-
%}
|
|
81
|
+
2. Create a helper folder `do` to symlink the `do/package.json` within:
|
|
287
82
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
{% endfor %}
|
|
83
|
+
```sh
|
|
84
|
+
mkdir do
|
|
85
|
+
cd ./do
|
|
86
|
+
ln -s ../node_modules/@anydigital/eleventy-bricks/src/do/package.json
|
|
293
87
|
```
|
|
294
88
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
A filter that filters collection items by checking if an attribute array includes a target value. Supports nested attribute names using dot notation.
|
|
298
|
-
|
|
299
|
-
**Why use this?**
|
|
300
|
-
|
|
301
|
-
When working with Eleventy collections, you often need to filter items based on tags or other array attributes in front matter. The `attr_includes` filter provides a flexible way to filter by any array attribute, with support for nested properties using dot notation.
|
|
302
|
-
|
|
303
|
-
**Usage:**
|
|
304
|
-
|
|
305
|
-
1. Enable the `attr_includes` filter in your Eleventy config:
|
|
89
|
+
3. Finally register `do` folder as npm workspace in your root `package.json`:
|
|
306
90
|
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
91
|
+
```json {data-caption=./package.json}
|
|
92
|
+
{
|
|
93
|
+
...
|
|
94
|
+
"workspaces": ["do"],
|
|
95
|
+
"scripts": {
|
|
96
|
+
"start": "npm -w do run start",
|
|
97
|
+
"stage": "npm -w do run stage",
|
|
98
|
+
"build": "npm -w do run build"
|
|
99
|
+
},
|
|
100
|
+
...
|
|
314
101
|
}
|
|
315
102
|
```
|
|
316
103
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
**Filter by array attribute (tags):**
|
|
320
|
-
|
|
321
|
-
```njk
|
|
322
|
-
{# Get all posts that include 'javascript' tag #}
|
|
323
|
-
{% set jsPosts = collections.all | attr_includes('data.tags', 'javascript') %}
|
|
324
|
-
|
|
325
|
-
{% for post in jsPosts %}
|
|
326
|
-
<h2>{{ post.data.title }}</h2>
|
|
327
|
-
{% endfor %}
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
**Parameters:**
|
|
331
|
-
|
|
332
|
-
- `collection`: The collection to filter (array of items)
|
|
333
|
-
- `attrName`: The attribute name to check (string, supports dot notation for nested properties)
|
|
334
|
-
- `targetValue`: The value to check for in the array (any type)
|
|
335
|
-
|
|
336
|
-
**Features:**
|
|
337
|
-
|
|
338
|
-
- Works with any array attribute in front matter
|
|
339
|
-
- Supports dot notation for nested properties (e.g., `'data.tags'`, `'data.author.roles'`)
|
|
340
|
-
- Returns empty array if collection is invalid
|
|
341
|
-
- Filters out items where the specified attribute is not an array or doesn't exist
|
|
342
|
-
|
|
343
|
-
**Examples:**
|
|
104
|
+
**Done!** 🎉 Now you can run:
|
|
344
105
|
|
|
345
|
-
|
|
106
|
+
- `npm start` to start 11ty dev server with live reload and Tailwind watch mode
|
|
107
|
+
- `npm run stage` to build and serve production-like site locally
|
|
108
|
+
- `npm run build` to finally build the site for production
|
|
109
|
+
- all available scripts: https://github.com/anydigital/eleventy-bricks/blob/main/src/do/package.json
|
|
346
110
|
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
title: My Post
|
|
350
|
-
category: blog
|
|
351
|
-
tags: [javascript, tutorial, beginner]
|
|
352
|
-
priority: 1
|
|
353
|
-
---
|
|
354
|
-
```
|
|
111
|
+
**Living example:** https://github.com/anydigital/sveleven
|
|
355
112
|
|
|
356
|
-
|
|
113
|
+
**Benefits:**
|
|
357
114
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
115
|
+
- **Clean separation**: Keep build scripts separate from project configuration
|
|
116
|
+
- **Reusable workflows**: Update scripts by upgrading the package
|
|
117
|
+
- **Workspace isolation**: Scripts run in their own workspace context
|
|
118
|
+
- **Easy maintenance**: No need to manually maintain build scripts
|
|
361
119
|
|
|
362
|
-
|
|
363
|
-
{% set highPriority = collections.all | attr_includes('data.priorities', 1) %}
|
|
120
|
+
<!--section-->
|
|
364
121
|
|
|
365
|
-
|
|
366
|
-
{% set recentTutorials = collections.all | attr_includes('data.tags', 'tutorial') | reverse | limit(5) %}
|
|
367
|
-
```
|
|
122
|
+
## Configuration Tools
|
|
368
123
|
|
|
369
|
-
|
|
124
|
+
<!--section:config-h3-->
|
|
370
125
|
|
|
371
|
-
|
|
126
|
+
### 🥷 Symlinked `eleventy.config.js` <br><sub>from https://github.com/anydigital/eleventy-bricks</sub> <a id="symlink-config"></a>
|
|
372
127
|
|
|
373
|
-
|
|
128
|
+
The package includes a fully-configured Eleventy config file `eleventy.config.js` that you can symlink to your project to get:
|
|
374
129
|
|
|
375
|
-
|
|
130
|
+
- All eleventy-bricks plugins enabled
|
|
131
|
+
- Eleventy Navigation plugin
|
|
132
|
+
- Table of Contents plugin (conditionally loaded if installed)
|
|
133
|
+
- Markdown-it with anchors and attributes
|
|
134
|
+
- YAML data support
|
|
135
|
+
- CLI input directory support
|
|
136
|
+
- Symlink support for development
|
|
137
|
+
- _and more_
|
|
376
138
|
|
|
377
|
-
**
|
|
139
|
+
**Benefits of symlinking:**
|
|
378
140
|
|
|
379
|
-
|
|
141
|
+
- **Always up-to-date**: Configuration automatically updates when you upgrade the package
|
|
142
|
+
- **Less maintenance**: No need to manually sync configuration changes
|
|
143
|
+
- **Quick setup**: Get started immediately with best-practice configurations
|
|
144
|
+
- **Easy customization**: Override specific settings by creating your own config that imports from the symlinked version
|
|
380
145
|
|
|
381
|
-
|
|
382
|
-
import { mergeFilter } from "@anydigital/eleventy-bricks";
|
|
146
|
+
**Installation as simple as:**
|
|
383
147
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
// eleventyConfig.addPlugin(eleventyBricks, { filters: ['merge'] });
|
|
388
|
-
}
|
|
148
|
+
```sh
|
|
149
|
+
npm install @anydigital/eleventy-bricks
|
|
150
|
+
ln -s ./node_modules/@anydigital/eleventy-bricks/src/eleventy.config.js
|
|
389
151
|
```
|
|
390
152
|
|
|
391
|
-
|
|
153
|
+
<!--section:cms-h3-->
|
|
392
154
|
|
|
393
|
-
|
|
155
|
+
<details><summary>
|
|
394
156
|
|
|
395
|
-
|
|
396
|
-
{# Combine two arrays #}
|
|
397
|
-
{% set allItems = featured | merge(regular) %}
|
|
157
|
+
### Symlinked CMS `index.html`
|
|
398
158
|
|
|
399
|
-
|
|
400
|
-
{% set combined = array1 | merge(array2, array3, array4) %}
|
|
401
|
-
|
|
402
|
-
{% for item in allItems %}
|
|
403
|
-
<p>{{ item }}</p>
|
|
404
|
-
{% endfor %}
|
|
405
|
-
```
|
|
159
|
+
</summary>
|
|
406
160
|
|
|
407
|
-
|
|
161
|
+
A ready-to-use Sveltia CMS admin interface for content management.
|
|
408
162
|
|
|
409
|
-
|
|
410
|
-
{# Merge configuration objects #}
|
|
411
|
-
{% set defaultConfig = { theme: 'light', lang: 'en' } %}
|
|
412
|
-
{% set userConfig = { theme: 'dark' } %}
|
|
413
|
-
{% set finalConfig = defaultConfig | merge(userConfig) %}
|
|
163
|
+
**Installation:**
|
|
414
164
|
|
|
415
|
-
|
|
165
|
+
```sh
|
|
166
|
+
mkdir -p ./src/admin
|
|
167
|
+
cd ./src/admin
|
|
168
|
+
ln -s ../../node_modules/@anydigital/eleventy-bricks/src/admin/index.html
|
|
416
169
|
```
|
|
417
170
|
|
|
418
|
-
|
|
171
|
+
</details>
|
|
419
172
|
|
|
420
|
-
|
|
421
|
-
- `...rest`: One or more arrays or objects to merge in
|
|
173
|
+
## Data Tools & Processors
|
|
422
174
|
|
|
423
|
-
|
|
175
|
+
<!--section:data&processors-h3-->
|
|
424
176
|
|
|
425
|
-
|
|
426
|
-
- Supports merging multiple items at once
|
|
427
|
-
- Non-mutating: Creates new arrays/objects, leaving originals unchanged
|
|
428
|
-
- For objects: Later values override earlier ones (shallow merge)
|
|
429
|
-
- For arrays: Concatenates all arrays together
|
|
430
|
-
- Handles null/undefined gracefully
|
|
177
|
+
### Global `siteData` helper
|
|
431
178
|
|
|
432
|
-
|
|
179
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
180
|
+
[`src/siteData.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/siteData.js)
|
|
433
181
|
|
|
434
|
-
|
|
435
|
-
{# Combine featured and regular posts #}
|
|
436
|
-
{% set featuredPosts = collections.all | attr_includes('data.featured', true) %}
|
|
437
|
-
{% set regularPosts = collections.all | attr_includes('data.featured', false) %}
|
|
438
|
-
{% set allPosts = featuredPosts | merge(regularPosts) %}
|
|
182
|
+
Adds global `site` data to your Eleventy project, providing commonly needed values that can be accessed in all templates:
|
|
439
183
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
comments: false
|
|
445
|
-
} %}
|
|
446
|
-
{% set pageMeta = defaultMeta | merge(page.data) %}
|
|
184
|
+
| Variable | Value |
|
|
185
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
186
|
+
| `{{ site.year }}` | The current year as a number (e.g., `2026`) |
|
|
187
|
+
| `{{ site.prod }}` | Boolean indicating if running in production mode (`true` for `eleventy build`, `false` for `eleventy serve`) |
|
|
447
188
|
|
|
448
|
-
|
|
449
|
-
{% set commonTags = ['javascript', 'html', 'css'] %}
|
|
450
|
-
{% set specialTags = page.data.tags or [] %}
|
|
451
|
-
{% set allTags = commonTags | merge(specialTags) %}
|
|
189
|
+
### 🥷 `autoLinkFavicons` transformer
|
|
452
190
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
#### `remove_tag`
|
|
458
|
-
|
|
459
|
-
A filter that removes a specified HTML element from provided HTML content. It removes the tag along with its content, including self-closing tags.
|
|
191
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
192
|
+
[`src/processors/autoLinkFavicons.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/processors/autoLinkFavicons.js)
|
|
460
193
|
|
|
461
|
-
|
|
194
|
+
Automatically adds favicon images from Google's favicon service to links that display plain URLs or domain names. This processor processes all HTML output files and adds inline favicon images next to link text that appears to be a plain URL.
|
|
462
195
|
|
|
463
|
-
When
|
|
196
|
+
**Why use this?** When you have links in your content that display raw URLs or domain names (like `https://example.com/page`), adding favicons provides a visual indicator of the external site. This processor automatically detects these plain-text URL links and enhances them with favicon images, making them more visually appealing and easier to recognize.
|
|
464
197
|
|
|
465
|
-
**
|
|
466
|
-
|
|
467
|
-
1. Enable the `remove_tag` filter in your Eleventy config:
|
|
468
|
-
|
|
469
|
-
```javascript
|
|
470
|
-
import { removeTagFilter } from "@anydigital/eleventy-bricks";
|
|
198
|
+
**How it works:**
|
|
471
199
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
```
|
|
200
|
+
1. Scans all HTML output files for `<a>` tags
|
|
201
|
+
2. Checks if the link text appears to be a plain URL or domain
|
|
202
|
+
3. Extracts the domain from the URL
|
|
203
|
+
4. Removes the domain from the link text (keeping only the path)
|
|
204
|
+
5. Adds a favicon image from Google's favicon service inline with the remaining text
|
|
478
205
|
|
|
479
|
-
|
|
206
|
+
**Example:**
|
|
480
207
|
|
|
481
|
-
|
|
482
|
-
{# Remove all script tags from content #}
|
|
483
|
-
{% set cleanContent = htmlContent | remove_tag('script') %}
|
|
208
|
+
Before processing:
|
|
484
209
|
|
|
485
|
-
|
|
210
|
+
```html
|
|
211
|
+
<a href="https://github.com/anydigital/eleventy-bricks">https://github.com/anydigital/eleventy-bricks</a>
|
|
486
212
|
```
|
|
487
213
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
- `html`: The HTML content to process (string)
|
|
491
|
-
- `tagName`: The tag name to remove (string)
|
|
492
|
-
|
|
493
|
-
**Features:**
|
|
494
|
-
|
|
495
|
-
- Removes both opening and closing tags along with their content
|
|
496
|
-
- Handles self-closing tags (e.g., `<br />`, `<img />`)
|
|
497
|
-
- Handles tags with attributes
|
|
498
|
-
- Case-insensitive matching
|
|
499
|
-
- Non-destructive: Returns new string, doesn't modify original
|
|
500
|
-
|
|
501
|
-
**Examples:**
|
|
214
|
+
After processing:
|
|
502
215
|
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
{# Strip specific formatting tags #}
|
|
510
|
-
{% set formatted = '<div><strong>Bold</strong> and <em>italic</em> text</div>' %}
|
|
511
|
-
{% set noStrong = formatted | remove_tag('strong') %}
|
|
512
|
-
{# Result: '<div>Bold and <em>italic</em> text</div>' #}
|
|
513
|
-
|
|
514
|
-
{# Chain multiple remove_tag filters for multiple tags #}
|
|
515
|
-
{% set richContent = page.content %}
|
|
516
|
-
{% set stripped = richContent
|
|
517
|
-
| remove_tag('script')
|
|
518
|
-
| remove_tag('style')
|
|
519
|
-
| remove_tag('iframe')
|
|
520
|
-
%}
|
|
521
|
-
|
|
522
|
-
{# Remove images for text-only preview #}
|
|
523
|
-
{% set textOnly = htmlContent | remove_tag('img') %}
|
|
216
|
+
```html
|
|
217
|
+
<a href="https://github.com/anydigital/eleventy-bricks" class="whitespace-nowrap" target="_blank">
|
|
218
|
+
<i><img src="https://www.google.com/s2/favicons?domain=github.com&sz=32" /></i>
|
|
219
|
+
<span>/anydigital/eleventy-bricks</span>
|
|
220
|
+
</a>
|
|
524
221
|
```
|
|
525
222
|
|
|
526
|
-
**
|
|
527
|
-
|
|
528
|
-
While this filter can help sanitize HTML content, it should not be relied upon as the sole security measure. For critical security requirements, use a dedicated HTML sanitization library on the server side before content reaches your templates.
|
|
223
|
+
**Rules:**
|
|
529
224
|
|
|
530
|
-
|
|
225
|
+
- Only applies to links where the text looks like a plain URL (contains the domain or starts with `http://`/`https://`)
|
|
226
|
+
- Removes the protocol and domain from the display text
|
|
227
|
+
- Removes the trailing slash from the display text
|
|
228
|
+
- Only applies if at least 3 characters remain after removing the domain (to avoid showing favicons for bare domain links)
|
|
229
|
+
- Uses Google's favicon service at `https://www.google.com/s2/favicons?domain=DOMAIN&sz=32`
|
|
230
|
+
- Adds `target="_blank"` to the processed links (only if not already present)
|
|
231
|
+
- Adds `whitespace-nowrap` class to the link
|
|
232
|
+
- Wraps the link text in a `<span>` element
|
|
233
|
+
- The favicon is wrapped in an `<i>` tag for easy styling
|
|
531
234
|
|
|
532
|
-
|
|
235
|
+
<details><summary>
|
|
533
236
|
|
|
534
|
-
|
|
237
|
+
### mdAutoRawTags preprocessor
|
|
535
238
|
|
|
536
|
-
|
|
239
|
+
</summary>
|
|
537
240
|
|
|
538
|
-
|
|
241
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
242
|
+
[`src/processors/markdown.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/processors/markdown.js)
|
|
539
243
|
|
|
540
|
-
|
|
244
|
+
Prevents Nunjucks syntax from being processed in Markdown files by automatically wrapping `{{`, `}}`, `{%`, and `%}` with `{% raw %}` tags.
|
|
541
245
|
|
|
542
|
-
|
|
543
|
-
import { sectionFilter } from "@anydigital/eleventy-bricks";
|
|
246
|
+
**Why use this?** When writing documentation or tutorials about templating in Markdown files, you often want to show Nunjucks/Liquid syntax as literal text. This preprocessor automatically escapes these special characters so they display as-is instead of being processed by the template engine.
|
|
544
247
|
|
|
545
|
-
|
|
546
|
-
sectionFilter(eleventyConfig);
|
|
547
|
-
// Or use as plugin:
|
|
548
|
-
// eleventyConfig.addPlugin(eleventyBricks, { filters: ['section'] });
|
|
549
|
-
}
|
|
550
|
-
```
|
|
248
|
+
**Example:**
|
|
551
249
|
|
|
552
|
-
|
|
250
|
+
Before `mdAutoRawTags`, writing this in Markdown:
|
|
553
251
|
|
|
554
252
|
```markdown
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
<!--section:intro-->
|
|
558
|
-
|
|
559
|
-
This is the introduction that appears at the top of the page.
|
|
560
|
-
|
|
561
|
-
<!--section:main-->
|
|
562
|
-
|
|
563
|
-
This is the main body of the post with all the details.
|
|
564
|
-
|
|
565
|
-
<!--section:summary,sidebar-->
|
|
566
|
-
|
|
567
|
-
This content appears in both the summary and the sidebar!
|
|
253
|
+
### Using {{ variable }} to output variables
|
|
568
254
|
```
|
|
569
255
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
```njk
|
|
573
|
-
{# Get the intro section #}
|
|
574
|
-
<div class="page-intro">
|
|
575
|
-
{{ content | section('intro') | safe }}
|
|
576
|
-
</div>
|
|
256
|
+
Would try to process `{{ variable }}` as a template variable. With `mdAutoRawTags`, it displays exactly as written.
|
|
577
257
|
|
|
578
|
-
|
|
579
|
-
<article>
|
|
580
|
-
{{ content | section('main') | safe }}
|
|
581
|
-
</article>
|
|
258
|
+
</details>
|
|
582
259
|
|
|
583
|
-
|
|
584
|
-
<aside>
|
|
585
|
-
{{ content | section('sidebar') | safe }}
|
|
586
|
-
</aside>
|
|
587
|
-
```
|
|
260
|
+
<details><summary>
|
|
588
261
|
|
|
589
|
-
|
|
262
|
+
### mdAutoNl2br converter
|
|
590
263
|
|
|
591
|
-
|
|
592
|
-
- `sectionName`: The name(s) of the section to extract (string)
|
|
264
|
+
</summary>
|
|
593
265
|
|
|
594
|
-
|
|
266
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
267
|
+
[`src/processors/markdown.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/processors/markdown.js)
|
|
595
268
|
|
|
596
|
-
|
|
597
|
-
- **Case-insensitive**: Section names are matched without regard to case
|
|
598
|
-
- **Multiple occurrences**: If a section name appears multiple times, the filter concatenates all matching sections
|
|
599
|
-
- **Non-destructive**: Returns extracted content without modifying the original input
|
|
600
|
-
- **EOF support**: Sections continue until the next `<!--section*-->` marker or the end of the file
|
|
269
|
+
Automatically converts `\n` sequences to `<br>` tags in Markdown content. This is particularly useful for adding line breaks inside Markdown tables where standard newlines don't work.
|
|
601
270
|
|
|
602
|
-
**
|
|
271
|
+
**Why use this?** Markdown tables don't support multi-line content in cells. By using `\n` in your content, this preprocessor will convert it to `<br>` tags, allowing you to display line breaks within table cells and other content.
|
|
603
272
|
|
|
604
|
-
|
|
605
|
-
{# Extract multiple sections with same name #}
|
|
606
|
-
{# Example content has two <!--section:note--> blocks #}
|
|
607
|
-
<div class="notes-box">
|
|
608
|
-
{{ content | section('note') | safe }}
|
|
609
|
-
</div>
|
|
273
|
+
**Example:**
|
|
610
274
|
|
|
611
|
-
|
|
612
|
-
{{ content | section('INTRO') | safe }}
|
|
275
|
+
In your Markdown file:
|
|
613
276
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
{% endif %}
|
|
277
|
+
```markdown
|
|
278
|
+
| Column 1 | Column 2 |
|
|
279
|
+
| ---------------------- | --------------------------------- |
|
|
280
|
+
| Line 1\nLine 2\nLine 3 | Another cell\nWith multiple lines |
|
|
619
281
|
```
|
|
620
282
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
- Sections start with: `<!--section:NAME-->` or `<!--section:NAME1,NAME2-->`
|
|
624
|
-
- Sections end at the next `<!--section*-->` marker or end of file
|
|
625
|
-
- Whitespace around names and inside comments is automatically trimmed
|
|
626
|
-
|
|
627
|
-
#### `if`
|
|
628
|
-
|
|
629
|
-
An inline conditional/ternary operator filter that returns one value if a condition is truthy, and another if it's falsy. Similar to Nunjucks' inline if syntax.
|
|
630
|
-
|
|
631
|
-
**Why use this?**
|
|
632
|
-
|
|
633
|
-
When you need simple conditional values in templates without verbose if/else blocks, the `if` filter provides a clean inline solution. It's especially useful for class names, attributes, or displaying alternate text based on conditions.
|
|
283
|
+
Will render as:
|
|
634
284
|
|
|
635
|
-
|
|
285
|
+
```html
|
|
286
|
+
<td>Line 1<br />Line 2<br />Line 3</td>
|
|
287
|
+
<td>Another cell<br />With multiple lines</td>
|
|
288
|
+
```
|
|
636
289
|
|
|
637
|
-
|
|
290
|
+
**Note:** This processes literal `\n` sequences (backslash followed by 'n'), not actual newline characters. Type `\n` in your source files where you want line breaks.
|
|
638
291
|
|
|
639
|
-
|
|
640
|
-
import { ifFilter } from "@anydigital/eleventy-bricks";
|
|
292
|
+
</details>
|
|
641
293
|
|
|
642
|
-
|
|
643
|
-
ifFilter(eleventyConfig);
|
|
644
|
-
// Or use as plugin:
|
|
645
|
-
// eleventyConfig.addPlugin(eleventyBricks, { filters: ['if'] });
|
|
646
|
-
}
|
|
647
|
-
```
|
|
294
|
+
<!--section:filters-h2-->
|
|
648
295
|
|
|
649
|
-
|
|
296
|
+
## 🥷 Universal 11ty Filters <small>for `.njk` & `.liquid`</small> <sub>from https://github.com/anydigital/eleventy-bricks</sub> <a id="filters"></a>
|
|
650
297
|
|
|
651
|
-
|
|
652
|
-
{# Basic usage #}
|
|
653
|
-
<div class="{{ 'active' | if: isActive, 'inactive' }}">Status</div>
|
|
298
|
+
<details><summary>
|
|
654
299
|
|
|
655
|
-
|
|
656
|
-
<span class="{{ 'highlight' | if: shouldHighlight }}">Text</span>
|
|
300
|
+
### `if`
|
|
657
301
|
|
|
658
|
-
|
|
659
|
-
{% set status = 'Published' | if: post.published, 'Draft' %}
|
|
660
|
-
```
|
|
302
|
+
</summary>
|
|
661
303
|
|
|
662
|
-
|
|
304
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
305
|
+
[`src/filters/if.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/if.js)
|
|
663
306
|
|
|
664
|
-
|
|
665
|
-
- `condition`: The condition to evaluate
|
|
666
|
-
- `falseValue`: The value to return if condition is falsy (optional, defaults to empty string)
|
|
307
|
+
An inline conditional/ternary operator filter that returns one value if a condition is truthy, and another if it's falsy. Similar to Nunjucks' inline if syntax, it is especially useful in `.liquid` templates.
|
|
667
308
|
|
|
668
309
|
**Features:**
|
|
669
310
|
|
|
@@ -672,11 +313,14 @@ export default function (eleventyConfig) {
|
|
|
672
313
|
- Default `falseValue` is an empty string if not provided
|
|
673
314
|
- Works with any data type for values
|
|
674
315
|
|
|
675
|
-
**Examples:**
|
|
316
|
+
**Examples:** <!-- @TODO: better examples -->
|
|
317
|
+
|
|
318
|
+
```jinja2
|
|
319
|
+
{# Basic usage (defaults to empty string) #}
|
|
320
|
+
<div class="{{ 'active' | if: isActive | default: 'inactive' }}">Status</div>
|
|
676
321
|
|
|
677
|
-
```njk
|
|
678
322
|
{# Toggle CSS classes #}
|
|
679
|
-
<button class="{{ 'btn-primary' | if: isPrimary
|
|
323
|
+
<button class="{{ 'btn-primary' | if: isPrimary | default: 'btn-secondary' }}">
|
|
680
324
|
Click me
|
|
681
325
|
</button>
|
|
682
326
|
|
|
@@ -699,171 +343,186 @@ export default function (eleventyConfig) {
|
|
|
699
343
|
{% set cssClass = 'featured' | if: post.featured | upper %}
|
|
700
344
|
```
|
|
701
345
|
|
|
702
|
-
|
|
346
|
+
</details>
|
|
703
347
|
|
|
704
|
-
|
|
348
|
+
<details><summary>
|
|
705
349
|
|
|
706
|
-
|
|
350
|
+
### `merge`
|
|
707
351
|
|
|
708
|
-
|
|
352
|
+
</summary>
|
|
709
353
|
|
|
710
|
-
|
|
354
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
355
|
+
[`src/filters/merge.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/merge.js)
|
|
711
356
|
|
|
712
|
-
|
|
357
|
+
A filter that merges arrays or objects together, similar to Twig's merge filter. For arrays, it concatenates them. For objects, it performs a shallow merge where later values override earlier ones.
|
|
713
358
|
|
|
714
|
-
|
|
715
|
-
import { attrConcatFilter } from "@anydigital/eleventy-bricks";
|
|
359
|
+
**Why use this?** When working with data in templates, you often need to combine multiple arrays or objects. The `merge` filter provides a clean way to merge data structures without writing custom JavaScript, making it easy to combine collections, merge configuration objects, or aggregate data from multiple sources.
|
|
716
360
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
}
|
|
361
|
+
**Examples:** <!-- @TODO: better examples -->
|
|
362
|
+
|
|
363
|
+
```jinja2
|
|
364
|
+
{# Merge configuration objects #}
|
|
365
|
+
{% set defaultConfig = { theme: 'light', lang: 'en' } %}
|
|
366
|
+
{% set userConfig = { theme: 'dark' } %}
|
|
367
|
+
{% set finalConfig = defaultConfig | merge(userConfig) %}
|
|
368
|
+
|
|
369
|
+
{# Result: { theme: 'dark', lang: 'en' } #}
|
|
722
370
|
```
|
|
723
371
|
|
|
724
|
-
|
|
372
|
+
```jinja2
|
|
373
|
+
{# Merge page metadata with defaults #}
|
|
374
|
+
{% set defaultMeta = {
|
|
375
|
+
author: 'Site Admin',
|
|
376
|
+
category: 'general',
|
|
377
|
+
comments: false
|
|
378
|
+
} %}
|
|
379
|
+
{% set pageMeta = defaultMeta | merge(page.data) %}
|
|
380
|
+
```
|
|
725
381
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
382
|
+
</details>
|
|
383
|
+
|
|
384
|
+
<details><summary>
|
|
385
|
+
|
|
386
|
+
### `attr_set`
|
|
729
387
|
|
|
730
|
-
|
|
731
|
-
{% set updatedPost = post | attr_concat('tags', 'important') %}
|
|
388
|
+
</summary>
|
|
732
389
|
|
|
733
|
-
|
|
734
|
-
|
|
390
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
391
|
+
[`src/filters/attr_set.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/attr_set.js)
|
|
392
|
+
|
|
393
|
+
A filter that creates a new object with an overridden attribute value. This is useful for modifying data objects in templates without mutating the original. Or even constructing an object from scratch.
|
|
394
|
+
|
|
395
|
+
#### Example: How to pass object(s) as argument(s) to a filter in `.liquid`?
|
|
396
|
+
|
|
397
|
+
```liquid {data-caption="trick for '| renderContent' filter"}
|
|
398
|
+
{% assign _ctx = null | attr_set: 'collections', collections %}
|
|
399
|
+
{{ ... | renderContent: 'liquid,md', _ctx }}
|
|
735
400
|
```
|
|
736
401
|
|
|
737
|
-
|
|
402
|
+
</details>
|
|
403
|
+
|
|
404
|
+
<details><summary>
|
|
738
405
|
|
|
739
|
-
|
|
740
|
-
- `attr`: The attribute name (must be an array or will be treated as one)
|
|
741
|
-
- `values`: Values to concatenate (can be an array, JSON string array, or single value)
|
|
406
|
+
### `attr_concat`
|
|
742
407
|
|
|
743
|
-
|
|
408
|
+
</summary>
|
|
744
409
|
|
|
745
|
-
|
|
410
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
411
|
+
[`src/filters/attr_concat.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/attr_concat.js)
|
|
412
|
+
|
|
413
|
+
A filter that concatenates values to an attribute array, returning a new object with the combined array. Useful for adding items to arrays like tags, classes, or other list-based attributes.
|
|
414
|
+
|
|
415
|
+
**Why use this?** When working with objects that have array attributes (like tags), you often need to add additional values without mutating the original object. The `attr_concat` filter provides a clean way to combine existing array values with new ones, automatically handling duplicates.
|
|
746
416
|
|
|
747
417
|
**Features:**
|
|
748
418
|
|
|
749
419
|
- Non-mutating: Creates a new object, leaving the original unchanged
|
|
750
420
|
- Automatically removes duplicates using Set
|
|
751
|
-
- Handles multiple input types: arrays, JSON string arrays, or single values
|
|
421
|
+
- Handles multiple input types: arrays, JSON string arrays (killer feature for `.liquid`), or single values
|
|
752
422
|
- Creates the attribute as an empty array if it doesn't exist
|
|
753
423
|
- Logs an error if the existing attribute is not an array
|
|
424
|
+
- `TBC:` Supports nested attributes (e.g., `data.tags`)
|
|
754
425
|
|
|
755
|
-
|
|
426
|
+
#### Example: Add tags to a post object in `.njk`:
|
|
756
427
|
|
|
757
|
-
```
|
|
758
|
-
{
|
|
759
|
-
{% set post = { title: 'My Post', tags: ['javascript'] } %}
|
|
760
|
-
{% set enhancedPost = post | attr_concat('tags', ['tutorial', 'beginner']) %}
|
|
761
|
-
{# Result: { title: 'My Post', tags: ['javascript', 'tutorial', 'beginner'] } #}
|
|
762
|
-
|
|
763
|
-
{# Add single value #}
|
|
764
|
-
{% set updatedPost = post | attr_concat('tags', 'featured') %}
|
|
765
|
-
{# Result: { title: 'My Post', tags: ['javascript', 'tutorial', 'beginner', 'featured'] } #}
|
|
766
|
-
|
|
767
|
-
{# No duplicates #}
|
|
768
|
-
{% set deduped = post | attr_concat('tags', ['javascript', 'advanced']) %}
|
|
769
|
-
{# Result: Only 'advanced' is added, 'javascript' already exists #}
|
|
770
|
-
|
|
771
|
-
{# Chain multiple attr_concat filters #}
|
|
772
|
-
{% set finalPost = post
|
|
773
|
-
| attr_concat('tags', 'popular')
|
|
774
|
-
| attr_concat('categories', ['tech', 'programming'])
|
|
775
|
-
%}
|
|
776
|
-
|
|
777
|
-
{# Use in loops to enhance collection items #}
|
|
778
|
-
{% for item in collections.posts %}
|
|
779
|
-
{% set enhancedItem = item | attr_concat('data.tags', 'blog') %}
|
|
780
|
-
{# ... use enhancedItem ... #}
|
|
781
|
-
{% endfor %}
|
|
428
|
+
```jinja2
|
|
429
|
+
{% set enhancedPost = post | attr_concat('tags', ['featured', 'popular']) %}
|
|
782
430
|
```
|
|
783
431
|
|
|
784
|
-
#### `
|
|
785
|
-
|
|
786
|
-
A filter that fetches content from remote URLs or local files. For remote URLs, it uses `@11ty/eleventy-fetch` to download and cache files. For local paths, it reads files relative to the input directory.
|
|
432
|
+
#### `PRO` Example: Add scripts and styles to the `site` object in `.liquid`:
|
|
787
433
|
|
|
788
|
-
|
|
434
|
+
```liquid
|
|
435
|
+
{% capture _ %}[
|
|
436
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-tomorrow.min.css",
|
|
437
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/plugins/treeview/prism-treeview.min.css",
|
|
438
|
+
"https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7/css/all.min.css",
|
|
439
|
+
"/styles.css"
|
|
440
|
+
]{% endcapture %}
|
|
441
|
+
{% assign site = site | attr_concat: 'styles', _ %}
|
|
789
442
|
|
|
790
|
-
|
|
443
|
+
{% capture _ %}[
|
|
444
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js",
|
|
445
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js",
|
|
446
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/plugins/treeview/prism-treeview.min.js"
|
|
447
|
+
]{% endcapture %}
|
|
448
|
+
{% assign site = site | attr_concat: 'scripts', _ %}
|
|
449
|
+
```
|
|
791
450
|
|
|
792
|
-
|
|
451
|
+
</details>
|
|
793
452
|
|
|
794
|
-
|
|
453
|
+
<details><summary>
|
|
795
454
|
|
|
796
|
-
|
|
797
|
-
npm install @11ty/eleventy-fetch
|
|
798
|
-
```
|
|
455
|
+
### `attr_includes`
|
|
799
456
|
|
|
800
|
-
>
|
|
457
|
+
</summary>
|
|
801
458
|
|
|
802
|
-
|
|
459
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
460
|
+
[`src/filters/attr_includes.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/attr_includes.js)
|
|
803
461
|
|
|
804
|
-
|
|
462
|
+
A filter that filters a list of items by checking if an attribute array includes a target value. Supports nested attribute names using dot notation.
|
|
805
463
|
|
|
806
|
-
|
|
807
|
-
npm install @11ty/eleventy-fetch
|
|
808
|
-
```
|
|
464
|
+
**Why use this?** When working with Eleventy collections, you often need to filter items based on tags or other array attributes in front matter. The `attr_includes` filter provides a flexible way to filter by any array attribute, with support for nested properties using dot notation.
|
|
809
465
|
|
|
810
|
-
|
|
466
|
+
#### Example: Get all posts that include `#javascript` tag
|
|
811
467
|
|
|
812
|
-
```
|
|
813
|
-
|
|
468
|
+
```jinja2 {data-caption="in .njk:"}
|
|
469
|
+
{% set js_posts = collections.all | attr_includes('data.tags', '#javascript') %}
|
|
814
470
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
// eleventyConfig.addPlugin(eleventyBricks, { filters: ['fetch'] });
|
|
819
|
-
}
|
|
471
|
+
{% for post in js_posts %}
|
|
472
|
+
<h2>{{ post.data.title }}</h2>
|
|
473
|
+
{% endfor %}
|
|
820
474
|
```
|
|
821
475
|
|
|
822
|
-
|
|
476
|
+
</details>
|
|
823
477
|
|
|
824
|
-
|
|
478
|
+
<details><summary>
|
|
825
479
|
|
|
826
|
-
|
|
827
|
-
{# Fetch content from a remote URL #}
|
|
828
|
-
{% set externalContent = "https://example.com/data.json" | fetch %}
|
|
829
|
-
{{ externalContent }}
|
|
480
|
+
### `fetch`
|
|
830
481
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
482
|
+
</summary>
|
|
483
|
+
|
|
484
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
485
|
+
[`src/filters/fetch.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/fetch.js)
|
|
835
486
|
|
|
836
|
-
|
|
487
|
+
A filter that fetches content from remote URLs or local files. For remote URLs, it uses `@11ty/eleventy-fetch` to download and cache files. For local paths, it reads files relative to the input directory.
|
|
837
488
|
|
|
838
|
-
|
|
839
|
-
{# Fetch content from a local file (relative to input directory) #}
|
|
840
|
-
{% set localData = "_data/content.txt" | fetch %}
|
|
841
|
-
{{ localData }}
|
|
489
|
+
**Why use this?** When building static sites, you often need to include content from external sources or reuse content from local files. The `fetch` filter provides a unified way to retrieve content from both remote URLs and local files, with automatic caching for remote resources to improve build performance.
|
|
842
490
|
|
|
843
|
-
|
|
844
|
-
{% set snippet = "_includes/snippets/example.md" | fetch %}
|
|
845
|
-
{{ snippet | markdown | safe }}
|
|
846
|
-
```
|
|
491
|
+
**Requirements:** This filter requires the `@11ty/eleventy-fetch` package to be installed:
|
|
847
492
|
|
|
848
|
-
|
|
493
|
+
```bash
|
|
494
|
+
npm install @11ty/eleventy-fetch
|
|
495
|
+
```
|
|
849
496
|
|
|
850
|
-
|
|
497
|
+
> `NOTE:` If `@11ty/eleventy-fetch` is not installed, this filter will not be available. The plugin automatically detects whether the package is installed and only enables the filter if it's present.
|
|
851
498
|
|
|
852
499
|
**Features:**
|
|
853
500
|
|
|
854
|
-
-
|
|
855
|
-
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
-
|
|
859
|
-
-
|
|
860
|
-
|
|
501
|
+
- Supports a URL (starting with `http://` or `https://`) or a local file path (relative to the input directory):
|
|
502
|
+
- **Remote URLs**: Downloads and caches content using `@11ty/eleventy-fetch`
|
|
503
|
+
- Caches files for 1 day by default
|
|
504
|
+
- Stores cached files in `[input-dir]/_downloads/` directory
|
|
505
|
+
- Automatically revalidates after cache expires
|
|
506
|
+
- **Local files**: Reads files relative to the Eleventy input directory
|
|
507
|
+
- No caching needed for local files
|
|
508
|
+
- Supports any file type that can be read as text
|
|
861
509
|
- **Error handling**: Throws descriptive errors if fetching fails
|
|
862
510
|
- **Conditional loading**: Only available when `@11ty/eleventy-fetch` is installed
|
|
863
511
|
|
|
512
|
+
**Use Cases:**
|
|
513
|
+
|
|
514
|
+
- Fetch content from external APIs during build time
|
|
515
|
+
- Include README files from GitHub repositories
|
|
516
|
+
- Reuse content from local files across multiple pages
|
|
517
|
+
- Download and inline external CSS or JavaScript
|
|
518
|
+
- Fetch data from headless CMS or external data sources
|
|
519
|
+
- Include shared content snippets without using Eleventy's include syntax
|
|
520
|
+
|
|
521
|
+
> `NOTE:` The filter returns raw text content. Use Eleventy's built-in filters like `| safe`, `| markdown`, or `| fromJson` to process the content as needed.
|
|
522
|
+
|
|
864
523
|
**Examples:**
|
|
865
524
|
|
|
866
|
-
```
|
|
525
|
+
```jinja2
|
|
867
526
|
{# Fetch and display remote content #}
|
|
868
527
|
{% set readme = "https://raw.githubusercontent.com/user/repo/main/README.md" | fetch %}
|
|
869
528
|
<div class="readme">
|
|
@@ -891,379 +550,152 @@ export default function (eleventyConfig) {
|
|
|
891
550
|
{{ sharedContent | safe }}
|
|
892
551
|
```
|
|
893
552
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
Remote files are cached in the `_downloads` folder within your input directory:
|
|
897
|
-
|
|
898
|
-
```
|
|
899
|
-
your-project/
|
|
900
|
-
├── src/ (or your input directory)
|
|
901
|
-
│ ├── _downloads/ (cached remote files)
|
|
902
|
-
│ ├── index.njk
|
|
903
|
-
│ └── ...
|
|
904
|
-
```
|
|
905
|
-
|
|
906
|
-
**Use Cases:**
|
|
907
|
-
|
|
908
|
-
- Fetch content from external APIs during build time
|
|
909
|
-
- Include README files from GitHub repositories
|
|
910
|
-
- Reuse content from local files across multiple pages
|
|
911
|
-
- Download and inline external CSS or JavaScript
|
|
912
|
-
- Fetch data from headless CMS or external data sources
|
|
913
|
-
- Include shared content snippets without using Eleventy's include syntax
|
|
914
|
-
|
|
915
|
-
**Note:** The filter returns raw text content. Use Eleventy's built-in filters like `| safe`, `| markdown`, or `| fromJson` to process the content as needed.
|
|
916
|
-
|
|
917
|
-
### Transforms
|
|
918
|
-
|
|
919
|
-
#### mdAutoRawTags
|
|
920
|
-
|
|
921
|
-
Prevents Nunjucks syntax from being processed in Markdown files by automatically wrapping `{{`, `}}`, `{%`, and `%}` with `{% raw %}` tags.
|
|
922
|
-
|
|
923
|
-
**Why use this?**
|
|
924
|
-
|
|
925
|
-
When writing documentation or tutorials about templating in Markdown files, you often want to show Nunjucks/Liquid syntax as literal text. This preprocessor automatically escapes these special characters so they display as-is instead of being processed by the template engine.
|
|
926
|
-
|
|
927
|
-
**Usage:**
|
|
928
|
-
|
|
929
|
-
1. Enable `mdAutoRawTags` in your Eleventy config:
|
|
930
|
-
|
|
931
|
-
```javascript
|
|
932
|
-
import { mdAutoRawTags } from "@anydigital/eleventy-bricks";
|
|
933
|
-
|
|
934
|
-
export default function (eleventyConfig) {
|
|
935
|
-
mdAutoRawTags(eleventyConfig);
|
|
936
|
-
// Or use as plugin:
|
|
937
|
-
// eleventyConfig.addPlugin(eleventyBricks, { mdAutoRawTags: true });
|
|
938
|
-
}
|
|
939
|
-
```
|
|
940
|
-
|
|
941
|
-
**Example:**
|
|
942
|
-
|
|
943
|
-
Before `mdAutoRawTags`, writing this in Markdown:
|
|
944
|
-
|
|
945
|
-
```markdown
|
|
946
|
-
Use {{ variable }} to output variables.
|
|
947
|
-
```
|
|
553
|
+
</details>
|
|
948
554
|
|
|
949
|
-
|
|
555
|
+
<details><summary>
|
|
950
556
|
|
|
951
|
-
|
|
557
|
+
### `section`
|
|
952
558
|
|
|
953
|
-
|
|
559
|
+
</summary>
|
|
954
560
|
|
|
955
|
-
|
|
561
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
562
|
+
[`src/filters/section.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/section.js)
|
|
956
563
|
|
|
957
|
-
|
|
564
|
+
A filter that extracts a named section from content marked with HTML comments. This is useful for splitting a single content file (like a Markdown post) into multiple parts that can be displayed and styled independently in your templates.
|
|
958
565
|
|
|
959
566
|
**Usage:**
|
|
960
567
|
|
|
961
|
-
1.
|
|
962
|
-
|
|
963
|
-
```javascript
|
|
964
|
-
import { mdAutoNl2br } from "@anydigital/eleventy-bricks";
|
|
965
|
-
|
|
966
|
-
export default function (eleventyConfig) {
|
|
967
|
-
mdAutoNl2br(eleventyConfig);
|
|
968
|
-
// Or use as plugin:
|
|
969
|
-
// eleventyConfig.addPlugin(eleventyBricks, { mdAutoNl2br: true });
|
|
970
|
-
}
|
|
971
|
-
```
|
|
972
|
-
|
|
973
|
-
**Example:**
|
|
568
|
+
1. Mark sections in your content file (e.g., `post.md`):
|
|
974
569
|
|
|
975
|
-
|
|
570
|
+
⚠️ `NOTE:` The `¡` symbol is used instead of `!` only to give examples below. Use `!` in your actual content files.
|
|
976
571
|
|
|
977
572
|
```markdown
|
|
978
|
-
|
|
979
|
-
| ---------------------- | --------------------------------- |
|
|
980
|
-
| Line 1\nLine 2\nLine 3 | Another cell\nWith multiple lines |
|
|
981
|
-
```
|
|
982
|
-
|
|
983
|
-
Will render as:
|
|
984
|
-
|
|
985
|
-
```html
|
|
986
|
-
<td>Line 1<br />Line 2<br />Line 3</td>
|
|
987
|
-
<td>Another cell<br />With multiple lines</td>
|
|
988
|
-
```
|
|
989
|
-
|
|
990
|
-
**Note:** This processes literal `\n` sequences (backslash followed by 'n'), not actual newline characters. Type `\n` in your source files where you want line breaks.
|
|
991
|
-
|
|
992
|
-
#### autoLinkFavicons
|
|
993
|
-
|
|
994
|
-
Automatically adds favicon images from Google's favicon service to links that display plain URLs or domain names. This transform processes all HTML output files and adds inline favicon images next to link text that appears to be a plain URL.
|
|
995
|
-
|
|
996
|
-
**Why use this?**
|
|
997
|
-
|
|
998
|
-
When you have links in your content that display raw URLs or domain names (like `https://example.com/page`), adding favicons provides a visual indicator of the external site. This transform automatically detects these plain-text URL links and enhances them with favicon images, making them more visually appealing and easier to recognize.
|
|
999
|
-
|
|
1000
|
-
**Usage:**
|
|
1001
|
-
|
|
1002
|
-
1. Enable `autoLinkFavicons` in your Eleventy config:
|
|
1003
|
-
|
|
1004
|
-
```javascript
|
|
1005
|
-
import { autoLinkFavicons } from "@anydigital/eleventy-bricks";
|
|
1006
|
-
|
|
1007
|
-
export default function (eleventyConfig) {
|
|
1008
|
-
autoLinkFavicons(eleventyConfig);
|
|
1009
|
-
// Or use as plugin:
|
|
1010
|
-
// eleventyConfig.addPlugin(eleventyBricks, { autoLinkFavicons: true });
|
|
1011
|
-
}
|
|
1012
|
-
```
|
|
1013
|
-
|
|
1014
|
-
**How it works:**
|
|
1015
|
-
|
|
1016
|
-
The transform:
|
|
1017
|
-
|
|
1018
|
-
1. Scans all HTML output files for `<a>` tags
|
|
1019
|
-
2. Checks if the link text appears to be a plain URL or domain
|
|
1020
|
-
3. Extracts the domain from the URL
|
|
1021
|
-
4. Removes the domain from the link text (keeping only the path)
|
|
1022
|
-
5. Adds a favicon image from Google's favicon service inline with the remaining text
|
|
1023
|
-
|
|
1024
|
-
**Example:**
|
|
1025
|
-
|
|
1026
|
-
Before transformation:
|
|
1027
|
-
|
|
1028
|
-
```html
|
|
1029
|
-
<a href="https://github.com/anydigital/eleventy-bricks">https://github.com/anydigital/eleventy-bricks</a>
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
After transformation:
|
|
1033
|
-
|
|
1034
|
-
```html
|
|
1035
|
-
<a href="https://github.com/anydigital/eleventy-bricks" class="whitespace-nowrap" target="_blank">
|
|
1036
|
-
<i><img src="https://www.google.com/s2/favicons?domain=github.com&sz=32" /></i>
|
|
1037
|
-
<span>/anydigital/eleventy-bricks</span>
|
|
1038
|
-
</a>
|
|
1039
|
-
```
|
|
1040
|
-
|
|
1041
|
-
**Rules:**
|
|
1042
|
-
|
|
1043
|
-
- Only applies to links where the text looks like a plain URL (contains the domain or starts with `http://`/`https://`)
|
|
1044
|
-
- Removes the protocol and domain from the display text
|
|
1045
|
-
- Removes the trailing slash from the display text
|
|
1046
|
-
- Only applies if at least 3 characters remain after removing the domain (to avoid showing favicons for bare domain links)
|
|
1047
|
-
- Uses Google's favicon service at `https://www.google.com/s2/favicons?domain=DOMAIN&sz=32`
|
|
1048
|
-
- Adds `target="_blank"` to the transformed links (only if not already present)
|
|
1049
|
-
- Adds `whitespace-nowrap` class to the link
|
|
1050
|
-
- Wraps the link text in a `<span>` element
|
|
1051
|
-
- The favicon is wrapped in an `<i>` tag for easy styling
|
|
1052
|
-
|
|
1053
|
-
**Styling:**
|
|
1054
|
-
|
|
1055
|
-
You can style the favicon icons with CSS:
|
|
1056
|
-
|
|
1057
|
-
```css
|
|
1058
|
-
/* Style the favicon wrapper */
|
|
1059
|
-
a i {
|
|
1060
|
-
display: inline-block;
|
|
1061
|
-
margin-right: 0.25em;
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
/* Style the favicon image */
|
|
1065
|
-
a i img {
|
|
1066
|
-
width: 16px;
|
|
1067
|
-
height: 16px;
|
|
1068
|
-
vertical-align: middle;
|
|
1069
|
-
}
|
|
1070
|
-
```
|
|
1071
|
-
|
|
1072
|
-
**Note:** This transform only processes HTML output files (those ending in `.html`). It does not modify the original content files.
|
|
1073
|
-
|
|
1074
|
-
### Global Data
|
|
1075
|
-
|
|
1076
|
-
Adds global site data to your Eleventy project, providing commonly needed values that can be accessed in all templates.
|
|
573
|
+
# My Post
|
|
1077
574
|
|
|
1078
|
-
|
|
575
|
+
<¡--section:intro-->
|
|
1079
576
|
|
|
1080
|
-
|
|
577
|
+
This is the introduction that appears at the top of the page.
|
|
1081
578
|
|
|
1082
|
-
|
|
579
|
+
<¡--section:main-->
|
|
1083
580
|
|
|
1084
|
-
|
|
581
|
+
This is the main body of the post with all the details.
|
|
1085
582
|
|
|
1086
|
-
|
|
1087
|
-
import { siteData } from "@anydigital/eleventy-bricks";
|
|
583
|
+
<¡--section:summary,sidebar-->
|
|
1088
584
|
|
|
1089
|
-
|
|
1090
|
-
siteData(eleventyConfig);
|
|
1091
|
-
// Or use as plugin:
|
|
1092
|
-
// eleventyConfig.addPlugin(eleventyBricks, { siteData: true });
|
|
1093
|
-
}
|
|
585
|
+
This content appears in both the summary and the sidebar!
|
|
1094
586
|
```
|
|
1095
587
|
|
|
1096
|
-
2. Use the
|
|
588
|
+
2. Use the filter in your templates: <!-- @TODO: better examples -->
|
|
1097
589
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
</footer>
|
|
1104
|
-
```
|
|
590
|
+
```jinja2
|
|
591
|
+
{# Get the intro section #}
|
|
592
|
+
<div class="page-intro">
|
|
593
|
+
{{ content | section('intro') | safe }}
|
|
594
|
+
</div>
|
|
1105
595
|
|
|
1106
|
-
|
|
596
|
+
{# Get the main section #}
|
|
597
|
+
<article>
|
|
598
|
+
{{ content | section('main') | safe }}
|
|
599
|
+
</article>
|
|
1107
600
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
{% else %}
|
|
1113
|
-
<!-- Development-only features -->
|
|
1114
|
-
<div class="dev-toolbar">Development Mode</div>
|
|
1115
|
-
{% endif %}
|
|
601
|
+
{# Get the sidebar section #}
|
|
602
|
+
<aside>
|
|
603
|
+
{{ content | section('sidebar') | safe }}
|
|
604
|
+
</aside>
|
|
1116
605
|
```
|
|
1117
606
|
|
|
1118
|
-
**Available Data:**
|
|
1119
|
-
|
|
1120
|
-
- `site.year`: The current year as a number (e.g., `2026`)
|
|
1121
|
-
- `site.prod`: Boolean indicating if running in production mode (`true` for `eleventy build`, `false` for `eleventy serve`)
|
|
1122
|
-
|
|
1123
607
|
**Features:**
|
|
1124
608
|
|
|
1125
|
-
-
|
|
1126
|
-
-
|
|
1127
|
-
-
|
|
1128
|
-
-
|
|
1129
|
-
|
|
1130
|
-
**Examples:**
|
|
1131
|
-
|
|
1132
|
-
```njk
|
|
1133
|
-
{# Copyright notice #}
|
|
1134
|
-
<p>Copyright © {{ site.year }} My Site</p>
|
|
1135
|
-
|
|
1136
|
-
{# Conditional loading of analytics #}
|
|
1137
|
-
{% if site.prod %}
|
|
1138
|
-
<script src="/analytics.js"></script>
|
|
1139
|
-
{% endif %}
|
|
1140
|
-
|
|
1141
|
-
{# Different behavior in dev vs prod #}
|
|
1142
|
-
{% if site.prod %}
|
|
1143
|
-
<link rel="stylesheet" href="/css/styles.min.css">
|
|
1144
|
-
{% else %}
|
|
1145
|
-
<link rel="stylesheet" href="/css/styles.css">
|
|
1146
|
-
<script src="/live-reload.js"></script>
|
|
1147
|
-
{% endif %}
|
|
1148
|
-
```
|
|
609
|
+
- **Multiple names**: A single section can have multiple names separated by commas: `<¡--section:name1,name2-->`
|
|
610
|
+
- **Case-insensitive**: Section names are matched without regard to case
|
|
611
|
+
- **Multiple occurrences**: If a section name appears multiple times, the filter concatenates all matching sections
|
|
612
|
+
- **Non-destructive**: Returns extracted content without modifying the original input
|
|
613
|
+
- **EOF support**: Sections continue until the next `<¡--section*-->` marker or the end of the file
|
|
1149
614
|
|
|
1150
|
-
|
|
615
|
+
**Syntax Rules:**
|
|
1151
616
|
|
|
1152
|
-
|
|
617
|
+
- Sections start with: `<¡--section:NAME-->` or `<¡--section:NAME1,NAME2-->`
|
|
618
|
+
- Sections end at the next `<¡--section*-->` marker or end of file
|
|
619
|
+
- Whitespace around names and inside comments is automatically trimmed
|
|
1153
620
|
|
|
1154
|
-
|
|
621
|
+
</details>
|
|
1155
622
|
|
|
1156
|
-
|
|
1157
|
-
- **Less maintenance**: No need to manually sync configuration changes
|
|
1158
|
-
- **Quick setup**: Get started immediately with best-practice configurations
|
|
1159
|
-
- **Easy customization**: Override specific settings by creating your own config that imports from the symlinked version
|
|
623
|
+
<details><summary>
|
|
1160
624
|
|
|
1161
|
-
|
|
625
|
+
### `remove_tag`
|
|
1162
626
|
|
|
1163
|
-
|
|
627
|
+
</summary>
|
|
1164
628
|
|
|
1165
|
-
|
|
629
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
630
|
+
[`src/filters/remove_tag.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/remove_tag.js)
|
|
1166
631
|
|
|
1167
|
-
|
|
1168
|
-
- Eleventy Navigation plugin
|
|
1169
|
-
- Table of Contents plugin (conditionally loaded if installed)
|
|
1170
|
-
- Markdown-it with anchors and attributes
|
|
1171
|
-
- YAML data support
|
|
1172
|
-
- CLI input directory support
|
|
1173
|
-
- Symlink support for development
|
|
632
|
+
A filter that removes a specified HTML element from provided HTML content. It removes the tag along with its content, including self-closing tags.
|
|
1174
633
|
|
|
1175
|
-
**
|
|
634
|
+
**Why use this?** When working with content from external sources or user-generated content, you may need to strip certain HTML tags for security or presentation purposes. The `remove_tag` filter provides a simple way to remove unwanted tags like `<script>`, `<style>`, or any other HTML elements from your content.
|
|
1176
635
|
|
|
1177
|
-
|
|
1178
|
-
npm install @11ty/eleventy-navigation markdown-it markdown-it-anchor markdown-it-attrs js-yaml minimist
|
|
1179
|
-
```
|
|
636
|
+
**Features:**
|
|
1180
637
|
|
|
1181
|
-
|
|
638
|
+
- Removes both opening and closing tags along with their content
|
|
639
|
+
- Handles self-closing tags (e.g., `<br />`, `<img />`)
|
|
640
|
+
- Handles tags with attributes
|
|
641
|
+
- Case-insensitive matching
|
|
642
|
+
- Non-destructive: Returns new string, doesn't modify original
|
|
1182
643
|
|
|
1183
|
-
|
|
1184
|
-
# For the fetch filter
|
|
1185
|
-
npm install @11ty/eleventy-fetch
|
|
644
|
+
**Security note:** While this filter can help sanitize HTML content, it should not be relied upon as the sole security measure. For critical security requirements, use a dedicated HTML sanitization library on the server side before content reaches your templates.
|
|
1186
645
|
|
|
1187
|
-
|
|
1188
|
-
npm install @uncenter/eleventy-plugin-toc
|
|
1189
|
-
```
|
|
646
|
+
#### Example: Remove all script tags from content <!-- @TODO: better examples -->
|
|
1190
647
|
|
|
1191
|
-
|
|
648
|
+
```jinja2
|
|
649
|
+
{% set cleanContent = htmlContent | remove_tag('script') %}
|
|
1192
650
|
|
|
1193
|
-
|
|
1194
|
-
ln -s node_modules/@anydigital/eleventy-bricks/src/eleventy.config.js eleventy.config.js
|
|
651
|
+
{{ cleanContent | safe }}
|
|
1195
652
|
```
|
|
1196
653
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
A ready-to-use Sveltia CMS admin interface for content management.
|
|
1200
|
-
|
|
1201
|
-
**Symlink to your project:**
|
|
654
|
+
</details>
|
|
1202
655
|
|
|
1203
|
-
|
|
1204
|
-
mkdir -p admin
|
|
1205
|
-
ln -s ../node_modules/@anydigital/eleventy-bricks/src/admin/index.html admin/index.html
|
|
1206
|
-
```
|
|
656
|
+
<details><summary>
|
|
1207
657
|
|
|
1208
|
-
|
|
658
|
+
### `strip_tag`
|
|
1209
659
|
|
|
1210
|
-
|
|
660
|
+
</summary>
|
|
1211
661
|
|
|
1212
|
-
|
|
662
|
+
🧩 [Install via Plugin](https://github.com/anydigital/eleventy-bricks#install) — or copy-paste from
|
|
663
|
+
[`src/filters/strip_tag.js`](https://github.com/anydigital/eleventy-bricks/blob/main/src/filters/strip_tag.js)
|
|
1213
664
|
|
|
1214
|
-
|
|
665
|
+
A filter that strips a specified HTML element from content while keeping its inner content intact. Only the opening and closing tags are removed; everything inside the tag is preserved in place.
|
|
1215
666
|
|
|
1216
|
-
|
|
667
|
+
**Why use this?** When rendering HTML from a CMS or external source you sometimes need to unwrap a specific element (e.g. remove a wrapping `<div>` or `<section>`) without losing the content it contains. Unlike `remove_tag`, which discards the entire element and its content, `strip_tag` surgically removes only the tags themselves.
|
|
1217
668
|
|
|
1218
|
-
|
|
1219
|
-
mkdir do
|
|
1220
|
-
```
|
|
669
|
+
**Features:**
|
|
1221
670
|
|
|
1222
|
-
|
|
671
|
+
- Removes only the opening and closing tags — inner content is preserved
|
|
672
|
+
- Handles tags with any attributes
|
|
673
|
+
- Strips all occurrences of the tag, including nested ones
|
|
674
|
+
- Case-insensitive matching
|
|
675
|
+
- Non-destructive: Returns a new string, leaves the original unchanged
|
|
1223
676
|
|
|
1224
|
-
|
|
1225
|
-
ln -s node_modules/@anydigital/eleventy-bricks/src/do/package.json do/package.json
|
|
1226
|
-
```
|
|
677
|
+
#### Example: Unwrap a wrapping `<div>` from content
|
|
1227
678
|
|
|
1228
|
-
|
|
679
|
+
```jinja2
|
|
680
|
+
{% set unwrapped = htmlContent | strip_tag('div') %}
|
|
1229
681
|
|
|
1230
|
-
|
|
1231
|
-
{
|
|
1232
|
-
"name": "my-project",
|
|
1233
|
-
"workspaces": ["do"],
|
|
1234
|
-
"scripts": {
|
|
1235
|
-
"build": "npm -w do run build",
|
|
1236
|
-
"start": "npm -w do run start"
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
682
|
+
{{ unwrapped | safe }}
|
|
1239
683
|
```
|
|
1240
684
|
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
Run your Eleventy project:
|
|
685
|
+
Input:
|
|
1244
686
|
|
|
1245
|
-
```
|
|
1246
|
-
|
|
687
|
+
```html
|
|
688
|
+
<div class="wrapper">
|
|
689
|
+
<p>Hello</p>
|
|
690
|
+
<p>World</p>
|
|
691
|
+
</div>
|
|
1247
692
|
```
|
|
1248
693
|
|
|
1249
|
-
|
|
694
|
+
Output:
|
|
1250
695
|
|
|
1251
|
-
```
|
|
1252
|
-
|
|
696
|
+
```html
|
|
697
|
+
<p>Hello</p>
|
|
698
|
+
<p>World</p>
|
|
1253
699
|
```
|
|
1254
700
|
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
- `build` - Build the site with Eleventy and minify CSS with Tailwind
|
|
1258
|
-
- `start` - Start Eleventy dev server with live reload and Tailwind watch mode
|
|
1259
|
-
- `stage` - Clean build and serve locally for preview
|
|
1260
|
-
- `11ty` - Run Eleventy commands directly
|
|
1261
|
-
- `11ty:clean` - Remove the `_site` output directory
|
|
1262
|
-
- `tw` - Run Tailwind CSS commands
|
|
1263
|
-
|
|
1264
|
-
**Benefits:**
|
|
1265
|
-
|
|
1266
|
-
- **Clean separation**: Keep build scripts separate from project configuration
|
|
1267
|
-
- **Reusable workflows**: Update scripts by upgrading the package
|
|
1268
|
-
- **Workspace isolation**: Scripts run in their own workspace context
|
|
1269
|
-
- **Easy maintenance**: No need to manually maintain build scripts
|
|
701
|
+
</details>
|