@anydigital/eleventy-bricks 0.24.0 → 0.26.0

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 CHANGED
@@ -1,4 +1,4 @@
1
- # eleventy-bricks
1
+ # `@anydigital/eleventy-bricks`
2
2
 
3
3
  A collection of helpful utilities and filters for Eleventy (11ty).
4
4
 
@@ -25,9 +25,9 @@ export default function (eleventyConfig) {
25
25
  eleventyConfig.addPlugin(eleventyBricks, {
26
26
  mdAutoRawTags: true,
27
27
  mdAutoNl2br: true,
28
- mdAutoLinkFavicons: true,
28
+ autoLinkFavicons: true,
29
29
  siteData: true,
30
- filters: ["attr", "where_in", "merge", "remove_tag", "if", "attr_concat", "fetch"],
30
+ filters: ["attr_set", "attr_includes", "merge", "remove_tag", "if", "attr_concat", "fetch"],
31
31
  });
32
32
 
33
33
  // Your other configuration...
@@ -43,9 +43,9 @@ module.exports = function (eleventyConfig) {
43
43
  eleventyConfig.addPlugin(eleventyBricks, {
44
44
  mdAutoRawTags: true,
45
45
  mdAutoNl2br: true,
46
- mdAutoLinkFavicons: true,
46
+ autoLinkFavicons: true,
47
47
  siteData: true,
48
- filters: ["attr", "where_in", "merge", "remove_tag", "if", "attr_concat", "fetch"],
48
+ filters: ["attr_set", "attr_includes", "merge", "remove_tag", "if", "attr_concat", "fetch"],
49
49
  });
50
50
 
51
51
  // Your other configuration...
@@ -64,9 +64,9 @@ Import only the specific helpers you need without using the plugin:
64
64
  import {
65
65
  mdAutoRawTags,
66
66
  mdAutoNl2br,
67
- mdAutoLinkFavicons,
68
- setAttrFilter,
69
- whereInFilter,
67
+ autoLinkFavicons,
68
+ attrSetFilter,
69
+ attrIncludesFilter,
70
70
  mergeFilter,
71
71
  removeTagFilter,
72
72
  ifFilter,
@@ -78,14 +78,17 @@ import {
78
78
  export default function (eleventyConfig) {
79
79
  mdAutoRawTags(eleventyConfig);
80
80
  mdAutoNl2br(eleventyConfig);
81
- mdAutoLinkFavicons(eleventyConfig);
82
- setAttrFilter(eleventyConfig);
83
- whereInFilter(eleventyConfig);
81
+ autoLinkFavicons(eleventyConfig);
82
+ attrSetFilter(eleventyConfig);
83
+ attrIncludesFilter(eleventyConfig);
84
84
  mergeFilter(eleventyConfig);
85
85
  removeTagFilter(eleventyConfig);
86
86
  ifFilter(eleventyConfig);
87
87
  attrConcatFilter(eleventyConfig);
88
- fetchFilter(eleventyConfig); // Only if @11ty/eleventy-fetch is installed
88
+ // fetchFilter is only available if @11ty/eleventy-fetch is installed
89
+ if (fetchFilter) {
90
+ fetchFilter(eleventyConfig);
91
+ }
89
92
  siteData(eleventyConfig);
90
93
 
91
94
  // Your other configuration...
@@ -98,9 +101,9 @@ export default function (eleventyConfig) {
98
101
  const {
99
102
  mdAutoRawTags,
100
103
  mdAutoNl2br,
101
- mdAutoLinkFavicons,
102
- setAttrFilter,
103
- whereInFilter,
104
+ autoLinkFavicons,
105
+ attrSetFilter,
106
+ attrIncludesFilter,
104
107
  mergeFilter,
105
108
  removeTagFilter,
106
109
  ifFilter,
@@ -112,14 +115,17 @@ const {
112
115
  module.exports = async function (eleventyConfig) {
113
116
  await mdAutoRawTags(eleventyConfig);
114
117
  await mdAutoNl2br(eleventyConfig);
115
- await mdAutoLinkFavicons(eleventyConfig);
116
- await setAttrFilter(eleventyConfig);
117
- await whereInFilter(eleventyConfig);
118
+ await autoLinkFavicons(eleventyConfig);
119
+ await attrSetFilter(eleventyConfig);
120
+ await attrIncludesFilter(eleventyConfig);
118
121
  await mergeFilter(eleventyConfig);
119
122
  await removeTagFilter(eleventyConfig);
120
123
  await ifFilter(eleventyConfig);
121
124
  await attrConcatFilter(eleventyConfig);
122
- await fetchFilter(eleventyConfig); // Only if @11ty/eleventy-fetch is installed
125
+ // fetchFilter is only available if @11ty/eleventy-fetch is installed
126
+ if (fetchFilter) {
127
+ await fetchFilter(eleventyConfig);
128
+ }
123
129
  await siteData(eleventyConfig);
124
130
 
125
131
  // Your other configuration...
@@ -132,18 +138,18 @@ module.exports = async function (eleventyConfig) {
132
138
 
133
139
  When using the plugin (Option 1), you can configure which helpers to enable:
134
140
 
135
- | Option | Type | Default | Description |
136
- | -------------------- | --------------- | ------- | ---------------------------------------------------------------- |
137
- | `mdAutoRawTags` | boolean | `false` | Enable the mdAutoRawTags preprocessor for Markdown files |
138
- | `mdAutoNl2br` | boolean | `false` | Enable the mdAutoNl2br preprocessor to convert \n to `<br>` tags |
139
- | `mdAutoLinkFavicons` | boolean | `false` | Enable the mdAutoLinkFavicons transform to add favicons to links |
140
- | `siteData` | boolean | `false` | Enable site.year and site.prod global data |
141
- | `filters` | array of string | `[]` | Array of filter names to enable (see Available Filters section) |
141
+ | Option | Type | Default | Description |
142
+ | ------------------ | --------------- | ------- | ---------------------------------------------------------------- |
143
+ | `mdAutoRawTags` | boolean | `false` | Enable the mdAutoRawTags preprocessor for Markdown files |
144
+ | `mdAutoNl2br` | boolean | `false` | Enable the mdAutoNl2br preprocessor to convert \n to `<br>` tags |
145
+ | `autoLinkFavicons` | boolean | `false` | Enable the autoLinkFavicons transform to add favicons to links |
146
+ | `siteData` | boolean | `false` | Enable site.year and site.prod global data |
147
+ | `filters` | array of string | `[]` | Array of filter names to enable (see Available Filters section) |
142
148
 
143
149
  **Available filter names for the `filters` array:**
144
150
 
145
- - `'attr'` - Override object attributes
146
- - `'where_in'` - Filter collections by attribute values
151
+ - `'attr_set'` - Override object attributes
152
+ - `'attr_includes'` - Filter collections by attribute values
147
153
  - `'merge'` - Merge arrays or objects
148
154
  - `'remove_tag'` - Remove HTML elements from content
149
155
  - `'if'` - Inline conditional/ternary operator
@@ -156,188 +162,80 @@ When using the plugin (Option 1), you can configure which helpers to enable:
156
162
  eleventyConfig.addPlugin(eleventyBricks, {
157
163
  mdAutoRawTags: true,
158
164
  mdAutoNl2br: true,
159
- mdAutoLinkFavicons: true,
165
+ autoLinkFavicons: true,
160
166
  siteData: true,
161
- filters: ["attr", "where_in", "merge", "remove_tag", "if", "attr_concat", "fetch"],
167
+ filters: ["attr_set", "attr_includes", "merge", "remove_tag", "if", "attr_concat", "fetch"],
162
168
  });
163
169
  ```
164
170
 
165
- ## Available 11ty Helpers
166
-
167
- ### mdAutoRawTags
168
-
169
- Prevents Nunjucks syntax from being processed in Markdown files by automatically wrapping `{{`, `}}`, `{%`, and `%}` with `{% raw %}` tags.
170
-
171
- **Why use this?**
172
-
173
- 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.
174
-
175
- **Usage:**
176
-
177
- 1. Enable `mdAutoRawTags` in your Eleventy config:
178
-
179
- ```javascript
180
- import { mdAutoRawTags } from "@anydigital/eleventy-bricks";
181
-
182
- export default function (eleventyConfig) {
183
- mdAutoRawTags(eleventyConfig);
184
- // Or use as plugin:
185
- // eleventyConfig.addPlugin(eleventyBricks, { mdAutoRawTags: true });
186
- }
187
- ```
188
-
189
- **Example:**
190
-
191
- Before `mdAutoRawTags`, writing this in Markdown:
192
-
193
- ```markdown
194
- Use {{ variable }} to output variables.
195
- ```
196
-
197
- Would try to process `{{ variable }}` as a template variable. With `mdAutoRawTags`, it displays exactly as written.
198
-
199
- ### mdAutoNl2br
200
-
201
- 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.
202
-
203
- **Why use this?**
204
-
205
- 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.
206
-
207
- **Usage:**
208
-
209
- 1. Enable `mdAutoNl2br` in your Eleventy config:
210
-
211
- ```javascript
212
- import { mdAutoNl2br } from "@anydigital/eleventy-bricks";
213
-
214
- export default function (eleventyConfig) {
215
- mdAutoNl2br(eleventyConfig);
216
- // Or use as plugin:
217
- // eleventyConfig.addPlugin(eleventyBricks, { mdAutoNl2br: true });
218
- }
219
- ```
220
-
221
- **Example:**
222
-
223
- In your Markdown file:
224
-
225
- ```markdown
226
- | Column 1 | Column 2 |
227
- | ---------------------- | --------------------------------- |
228
- | Line 1\nLine 2\nLine 3 | Another cell\nWith multiple lines |
229
- ```
230
-
231
- Will render as:
232
-
233
- ```html
234
- <td>Line 1<br />Line 2<br />Line 3</td>
235
- <td>Another cell<br />With multiple lines</td>
236
- ```
237
-
238
- **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.
239
-
240
- ### mdAutoLinkFavicons
241
-
242
- 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.
243
-
244
- **Why use this?**
245
-
246
- 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.
247
-
248
- **Usage:**
249
-
250
- 1. Enable `mdAutoLinkFavicons` in your Eleventy config:
251
-
252
- ```javascript
253
- import { mdAutoLinkFavicons } from "@anydigital/eleventy-bricks";
254
-
255
- export default function (eleventyConfig) {
256
- mdAutoLinkFavicons(eleventyConfig);
257
- // Or use as plugin:
258
- // eleventyConfig.addPlugin(eleventyBricks, { mdAutoLinkFavicons: true });
259
- }
260
- ```
261
-
262
- **How it works:**
263
-
264
- The transform:
265
-
266
- 1. Scans all HTML output files for `<a>` tags
267
- 2. Checks if the link text appears to be a plain URL or domain
268
- 3. Extracts the domain from the URL
269
- 4. Removes the domain from the link text (keeping only the path)
270
- 5. Adds a favicon image from Google's favicon service inline with the remaining text
271
-
272
- **Example:**
171
+ ### Additional Exports
273
172
 
274
- Before transformation:
173
+ The plugin also exports the following utility functions for advanced usage:
275
174
 
276
- ```html
277
- <a href="https://github.com/anydigital/eleventy-bricks">https://github.com/anydigital/eleventy-bricks</a>
278
- ```
175
+ - `transformAutoRaw(content)`: The transform function used by `mdAutoRawTags` preprocessor. Can be used programmatically to wrap Nunjucks syntax with raw tags.
176
+ - `transformNl2br(content)`: The transform function used by `mdAutoNl2br` preprocessor. Can be used programmatically to convert `\n` sequences to `<br>` tags.
177
+ - `isPlainUrlText(linkText, domain)`: Helper function that checks if link text looks like a plain URL or domain.
178
+ - `cleanLinkText(linkText, domain)`: Helper function that cleans link text by removing protocol, domain, and leading slash.
179
+ - `buildFaviconLink(attrs, domain, text)`: Helper function that builds HTML for a link with favicon.
180
+ - `transformLink(match, attrs, url, linkText)`: The transform function used by `autoLinkFavicons` that transforms a single link to include a favicon.
181
+ - `replaceLinksInHtml(content, transformer)`: Helper function that replaces all anchor links in HTML content with transformed versions.
182
+ - `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.
183
+ - `merge(first, ...rest)`: The core merge function used by the `merge` filter. Can be used programmatically to merge arrays or objects.
184
+ - `removeTag(html, tagName)`: The core function used by the `remove_tag` filter. Can be used programmatically to remove HTML tags from content.
185
+ - `iff(trueValue, condition, falseValue)`: The core conditional function used by the `if` filter. Can be used programmatically as a ternary operator.
186
+ - `attrConcat(obj, attr, values)`: The core function used by the `attr_concat` filter. Can be used programmatically to concatenate values to an attribute array.
187
+ - `attrSet(obj, key, value)`: The core function used by the `attr_set` filter. Can be used programmatically to override object attributes.
279
188
 
280
- After transformation:
189
+ <!--TRICKS-->
281
190
 
282
- ```html
283
- <a href="https://github.com/anydigital/eleventy-bricks" class="whitespace-nowrap" target="_blank">
284
- <i><img src="https://www.google.com/s2/favicons?domain=github.com&sz=32" /></i>
285
- <span>/anydigital/eleventy-bricks</span>
286
- </a>
287
- ```
191
+ ## Tricks from [Eleventy Bricks](https://github.com/anydigital/eleventy-bricks) {#eleventy-bricks}
288
192
 
289
- **Rules:**
193
+ ### Filters
290
194
 
291
- - Only applies to links where the text looks like a plain URL (contains the domain or starts with `http://`/`https://`)
292
- - Removes the protocol and domain from the display text
293
- - Removes the trailing slash from the display text
294
- - Only applies if at least 3 characters remain after removing the domain (to avoid showing favicons for bare domain links)
295
- - Uses Google's favicon service at `https://www.google.com/s2/favicons?domain=DOMAIN&sz=32`
296
- - Adds `target="_blank"` to the transformed links (only if not already present)
297
- - Adds `whitespace-nowrap` class to the link
298
- - Wraps the link text in a `<span>` element
299
- - The favicon is wrapped in an `<i>` tag for easy styling
195
+ | Input | Nunjucks | Liquid <hr> |
196
+ | ---------: | ------------------------------------------------------------------------------ | ---------------------------------------------------- |
197
+ | {.divider} | Logical |
198
+ | `ANY \| ` | `default(VALUE)` <br>= `d(...)` | `default: VALUE` |
199
+ | `ANY \|` | [`if(TEST, OP, VALUE)`](#if) <sub>currently only `if(TEST)`</sub> | [`if: TEST, OP, VALUE`](#if) |
200
+ | {.divider} | On objects |
201
+ | `OBJ \|` | [`merge(OBJ2)`](#merge) | [`merge: OBJ2`](#merge) |
202
+ | {.divider} | On object attributes |
203
+ | `OBJ \|` | `selectattr(BOOL_ATTR)` | `where: ATTR, VALUE` |
204
+ | `OBJ \|` | `rejectattr(BOOL_ATTR)` | N/A |
205
+ | `OBJ \|` | [`attr_includes(ARRAY_ATTR, VALUE)`](#attr_includes) <sub>was `where_in`</sub> | [`attr_includes: ARRAY_ATTR, VALUE`](#attr_includes) |
206
+ | `OBJ \|` | [`attr_set(ATTR, VALUE)`](#attr_set) <sub>was `attr`</sub> | [`attr_set: ATTR, VALUE`](#attr_set) |
207
+ | `OBJ \|` | [`attr_concat(ARRAY_ATTR, ARRAY2)`](#attr_concat) | [`attr_concat: ARRAY_ATTR, ARRAY2`](#attr_concat) |
208
+ | {.divider} | Textual |
209
+ | `HTML \|` | `striptags` | `strip_html` |
210
+ | `HTML \|` | [`remove_tag(TAG)`](#remove_tag) | [`remove_tag: TAG`](#remove_tag) |
211
+ | `STR \|` | `remove: STR2` | `remove: STR2` |
212
+ | {.divider} | Other |
213
+ | `URL \|` | [`fetch`](#fetch) | [`fetch`](#fetch) |
300
214
 
301
- **Styling:**
215
+ Ref:
302
216
 
303
- You can style the favicon icons with CSS:
217
+ - https://mozilla.github.io/nunjucks/templating.html#builtin-filters
218
+ - https://shopify.github.io/liquid/
304
219
 
305
- ```css
306
- /* Style the favicon wrapper */
307
- a i {
308
- display: inline-block;
309
- margin-right: 0.25em;
310
- }
311
-
312
- /* Style the favicon image */
313
- a i img {
314
- width: 16px;
315
- height: 16px;
316
- vertical-align: middle;
317
- }
318
- ```
319
-
320
- **Note:** This transform only processes HTML output files (those ending in `.html`). It does not modify the original content files.
321
-
322
- ### attr
220
+ #### `attr_set`
323
221
 
324
222
  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.
325
223
 
326
224
  **Why use this?**
327
225
 
328
- When working with Eleventy data, you sometimes need to modify an object's properties for a specific use case. The `attr` filter provides a clean way to create a modified copy of an object without affecting the original.
226
+ 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.
329
227
 
330
228
  **Usage:**
331
229
 
332
- 1. Enable the `attr` filter in your Eleventy config:
230
+ 1. Enable the `attr_set` filter in your Eleventy config:
333
231
 
334
232
  ```javascript
335
- import { setAttrFilter } from "@anydigital/eleventy-bricks";
233
+ import { attrSetFilter } from "@anydigital/eleventy-bricks";
336
234
 
337
235
  export default function (eleventyConfig) {
338
- setAttrFilter(eleventyConfig);
236
+ attrSetFilter(eleventyConfig);
339
237
  // Or use as plugin:
340
- // eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr'] });
238
+ // eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr_set'] });
341
239
  }
342
240
  ```
343
241
 
@@ -345,7 +243,7 @@ export default function (eleventyConfig) {
345
243
 
346
244
  ```njk
347
245
  {# Create a modified version of a page object #}
348
- {% set modifiedPage = page | attr('title', 'New Title') %}
246
+ {% set modifiedPage = page | attr_set('title', 'New Title') %}
349
247
 
350
248
  <h1>{{ modifiedPage.title }}</h1>
351
249
  <p>Original title: {{ page.title }}</p>
@@ -372,61 +270,50 @@ A new object with the specified attribute set to the given value. The original o
372
270
 
373
271
  ```njk
374
272
  {# Override a single attribute #}
375
- {% set updatedPost = post | attr('featured', true) %}
273
+ {% set updatedPost = post | attr_set('featured', true) %}
376
274
 
377
- {# Chain multiple attr filters #}
275
+ {# Chain multiple attr_set filters #}
378
276
  {% set modifiedPost = post
379
- | attr('category', 'blog')
380
- | attr('priority', 1)
277
+ | attr_set('category', 'blog')
278
+ | attr_set('priority', 1)
381
279
  %}
382
280
 
383
281
  {# Use in loops #}
384
282
  {% for item in collection %}
385
- {% set enhancedItem = item | attr('processed', true) %}
283
+ {% set enhancedItem = item | attr_set('processed', true) %}
386
284
  {# ... use enhancedItem ... #}
387
285
  {% endfor %}
388
286
  ```
389
287
 
390
- ### where_in
288
+ #### `attr_includes`
391
289
 
392
- A filter that filters collection items by attribute value. It checks if an item's attribute matches a target value. If the attribute is an array, it checks if the array includes the target value. Supports nested attribute names using dot notation.
290
+ A filter that filters collection items by checking if an attribute array includes a target value. Supports nested attribute names using dot notation.
393
291
 
394
292
  **Why use this?**
395
293
 
396
- When working with Eleventy collections, you often need to filter items based on front matter data. The `where_in` filter provides a flexible way to filter by any attribute, with special handling for array attributes (like tags) and support for nested properties using dot notation.
294
+ 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.
397
295
 
398
296
  **Usage:**
399
297
 
400
- 1. Enable the `where_in` filter in your Eleventy config:
298
+ 1. Enable the `attr_includes` filter in your Eleventy config:
401
299
 
402
300
  ```javascript
403
- import { whereInFilter } from "@anydigital/eleventy-bricks";
301
+ import { attrIncludesFilter } from "@anydigital/eleventy-bricks";
404
302
 
405
303
  export default function (eleventyConfig) {
406
- whereInFilter(eleventyConfig);
304
+ attrIncludesFilter(eleventyConfig);
407
305
  // Or use as plugin:
408
- // eleventyConfig.addPlugin(eleventyBricks, { filters: ['where_in'] });
306
+ // eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr_includes'] });
409
307
  }
410
308
  ```
411
309
 
412
310
  2. Use the filter in your templates:
413
311
 
414
- **Filter by exact attribute match:**
415
-
416
- ```njk
417
- {# Get all posts with category 'blog' #}
418
- {% set blogPosts = collections.all | where_in('data.category', 'blog') %}
419
-
420
- {% for post in blogPosts %}
421
- <h2>{{ post.data.title }}</h2>
422
- {% endfor %}
423
- ```
424
-
425
312
  **Filter by array attribute (tags):**
426
313
 
427
314
  ```njk
428
315
  {# Get all posts that include 'javascript' tag #}
429
- {% set jsPosts = collections.all | where_in('data.tags', 'javascript') %}
316
+ {% set jsPosts = collections.all | attr_includes('data.tags', 'javascript') %}
430
317
 
431
318
  {% for post in jsPosts %}
432
319
  <h2>{{ post.data.title }}</h2>
@@ -437,15 +324,14 @@ export default function (eleventyConfig) {
437
324
 
438
325
  - `collection`: The collection to filter (array of items)
439
326
  - `attrName`: The attribute name to check (string, supports dot notation for nested properties)
440
- - `targetValue`: The value to match against (any type)
327
+ - `targetValue`: The value to check for in the array (any type)
441
328
 
442
329
  **Features:**
443
330
 
444
- - Works with any attribute in front matter
445
- - Supports dot notation for nested properties (e.g., `'data.tags'`, `'data.author.name'`)
446
- - Special handling for array attributes (uses `includes()` check)
331
+ - Works with any array attribute in front matter
332
+ - Supports dot notation for nested properties (e.g., `'data.tags'`, `'data.author.roles'`)
447
333
  - Returns empty array if collection is invalid
448
- - Filters out items without the specified attribute
334
+ - Filters out items where the specified attribute is not an array or doesn't exist
449
335
 
450
336
  **Examples:**
451
337
 
@@ -463,20 +349,17 @@ priority: 1
463
349
  Template usage:
464
350
 
465
351
  ```njk
466
- {# Filter by category (using dot notation for nested properties) #}
467
- {% set blogPosts = collections.all | where_in('data.category', 'blog') %}
468
-
469
- {# Filter by tag (array) #}
470
- {% set jsTutorials = collections.all | where_in('data.tags', 'javascript') %}
352
+ {# Filter by tag (array) using dot notation for nested properties #}
353
+ {% set jsTutorials = collections.all | attr_includes('data.tags', 'javascript') %}
471
354
 
472
- {# Filter by numeric value #}
473
- {% set highPriority = collections.all | where_in('data.priority', 1) %}
355
+ {# Filter by numeric value in array #}
356
+ {% set highPriority = collections.all | attr_includes('data.priorities', 1) %}
474
357
 
475
358
  {# Chain filters #}
476
- {% set recentBlogPosts = collections.all | where_in('data.category', 'blog') | reverse | limit(5) %}
359
+ {% set recentTutorials = collections.all | attr_includes('data.tags', 'tutorial') | reverse | limit(5) %}
477
360
  ```
478
361
 
479
- ### merge
362
+ #### `merge`
480
363
 
481
364
  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.
482
365
 
@@ -543,8 +426,8 @@ export default function (eleventyConfig) {
543
426
 
544
427
  ```njk
545
428
  {# Combine featured and regular posts #}
546
- {% set featuredPosts = collections.all | where_in('data.featured', true) %}
547
- {% set regularPosts = collections.all | where_in('data.featured', false) %}
429
+ {% set featuredPosts = collections.all | attr_includes('data.featured', true) %}
430
+ {% set regularPosts = collections.all | attr_includes('data.featured', false) %}
548
431
  {% set allPosts = featuredPosts | merge(regularPosts) %}
549
432
 
550
433
  {# Merge page metadata with defaults #}
@@ -564,7 +447,7 @@ export default function (eleventyConfig) {
564
447
  {% set config = defaults | merge(siteConfig, pageConfig, userPrefs) %}
565
448
  ```
566
449
 
567
- ### remove_tag
450
+ #### `remove_tag`
568
451
 
569
452
  A filter that removes a specified HTML element from provided HTML content. It removes the tag along with its content, including self-closing tags.
570
453
 
@@ -637,7 +520,7 @@ export default function (eleventyConfig) {
637
520
 
638
521
  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.
639
522
 
640
- ### if
523
+ #### `if`
641
524
 
642
525
  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.
643
526
 
@@ -712,7 +595,7 @@ export default function (eleventyConfig) {
712
595
  {% set cssClass = 'featured' | if: post.featured | upper %}
713
596
  ```
714
597
 
715
- ### attr_concat
598
+ #### `attr_concat`
716
599
 
717
600
  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.
718
601
 
@@ -794,7 +677,7 @@ A new object with the specified attribute containing the combined unique array.
794
677
  {% endfor %}
795
678
  ```
796
679
 
797
- ### fetch
680
+ #### `fetch`
798
681
 
799
682
  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.
800
683
 
@@ -927,7 +810,164 @@ your-project/
927
810
 
928
811
  **Note:** The filter returns raw text content. Use Eleventy's built-in filters like `| safe`, `| markdown`, or `| fromJson` to process the content as needed.
929
812
 
930
- ### siteData
813
+ ### Transforms
814
+
815
+ #### mdAutoRawTags
816
+
817
+ Prevents Nunjucks syntax from being processed in Markdown files by automatically wrapping `{{`, `}}`, `{%`, and `%}` with `{% raw %}` tags.
818
+
819
+ **Why use this?**
820
+
821
+ 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.
822
+
823
+ **Usage:**
824
+
825
+ 1. Enable `mdAutoRawTags` in your Eleventy config:
826
+
827
+ ```javascript
828
+ import { mdAutoRawTags } from "@anydigital/eleventy-bricks";
829
+
830
+ export default function (eleventyConfig) {
831
+ mdAutoRawTags(eleventyConfig);
832
+ // Or use as plugin:
833
+ // eleventyConfig.addPlugin(eleventyBricks, { mdAutoRawTags: true });
834
+ }
835
+ ```
836
+
837
+ **Example:**
838
+
839
+ Before `mdAutoRawTags`, writing this in Markdown:
840
+
841
+ ```markdown
842
+ Use {{ variable }} to output variables.
843
+ ```
844
+
845
+ Would try to process `{{ variable }}` as a template variable. With `mdAutoRawTags`, it displays exactly as written.
846
+
847
+ #### mdAutoNl2br
848
+
849
+ 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.
850
+
851
+ **Why use this?**
852
+
853
+ 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.
854
+
855
+ **Usage:**
856
+
857
+ 1. Enable `mdAutoNl2br` in your Eleventy config:
858
+
859
+ ```javascript
860
+ import { mdAutoNl2br } from "@anydigital/eleventy-bricks";
861
+
862
+ export default function (eleventyConfig) {
863
+ mdAutoNl2br(eleventyConfig);
864
+ // Or use as plugin:
865
+ // eleventyConfig.addPlugin(eleventyBricks, { mdAutoNl2br: true });
866
+ }
867
+ ```
868
+
869
+ **Example:**
870
+
871
+ In your Markdown file:
872
+
873
+ ```markdown
874
+ | Column 1 | Column 2 |
875
+ | ---------------------- | --------------------------------- |
876
+ | Line 1\nLine 2\nLine 3 | Another cell\nWith multiple lines |
877
+ ```
878
+
879
+ Will render as:
880
+
881
+ ```html
882
+ <td>Line 1<br />Line 2<br />Line 3</td>
883
+ <td>Another cell<br />With multiple lines</td>
884
+ ```
885
+
886
+ **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.
887
+
888
+ #### autoLinkFavicons
889
+
890
+ 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.
891
+
892
+ **Why use this?**
893
+
894
+ 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.
895
+
896
+ **Usage:**
897
+
898
+ 1. Enable `autoLinkFavicons` in your Eleventy config:
899
+
900
+ ```javascript
901
+ import { autoLinkFavicons } from "@anydigital/eleventy-bricks";
902
+
903
+ export default function (eleventyConfig) {
904
+ autoLinkFavicons(eleventyConfig);
905
+ // Or use as plugin:
906
+ // eleventyConfig.addPlugin(eleventyBricks, { autoLinkFavicons: true });
907
+ }
908
+ ```
909
+
910
+ **How it works:**
911
+
912
+ The transform:
913
+
914
+ 1. Scans all HTML output files for `<a>` tags
915
+ 2. Checks if the link text appears to be a plain URL or domain
916
+ 3. Extracts the domain from the URL
917
+ 4. Removes the domain from the link text (keeping only the path)
918
+ 5. Adds a favicon image from Google's favicon service inline with the remaining text
919
+
920
+ **Example:**
921
+
922
+ Before transformation:
923
+
924
+ ```html
925
+ <a href="https://github.com/anydigital/eleventy-bricks">https://github.com/anydigital/eleventy-bricks</a>
926
+ ```
927
+
928
+ After transformation:
929
+
930
+ ```html
931
+ <a href="https://github.com/anydigital/eleventy-bricks" class="whitespace-nowrap" target="_blank">
932
+ <i><img src="https://www.google.com/s2/favicons?domain=github.com&sz=32" /></i>
933
+ <span>/anydigital/eleventy-bricks</span>
934
+ </a>
935
+ ```
936
+
937
+ **Rules:**
938
+
939
+ - Only applies to links where the text looks like a plain URL (contains the domain or starts with `http://`/`https://`)
940
+ - Removes the protocol and domain from the display text
941
+ - Removes the trailing slash from the display text
942
+ - Only applies if at least 3 characters remain after removing the domain (to avoid showing favicons for bare domain links)
943
+ - Uses Google's favicon service at `https://www.google.com/s2/favicons?domain=DOMAIN&sz=32`
944
+ - Adds `target="_blank"` to the transformed links (only if not already present)
945
+ - Adds `whitespace-nowrap` class to the link
946
+ - Wraps the link text in a `<span>` element
947
+ - The favicon is wrapped in an `<i>` tag for easy styling
948
+
949
+ **Styling:**
950
+
951
+ You can style the favicon icons with CSS:
952
+
953
+ ```css
954
+ /* Style the favicon wrapper */
955
+ a i {
956
+ display: inline-block;
957
+ margin-right: 0.25em;
958
+ }
959
+
960
+ /* Style the favicon image */
961
+ a i img {
962
+ width: 16px;
963
+ height: 16px;
964
+ vertical-align: middle;
965
+ }
966
+ ```
967
+
968
+ **Note:** This transform only processes HTML output files (those ending in `.html`). It does not modify the original content files.
969
+
970
+ ### Global Data
931
971
 
932
972
  Adds global site data to your Eleventy project, providing commonly needed values that can be accessed in all templates.
933
973
 
@@ -1003,26 +1043,18 @@ export default function (eleventyConfig) {
1003
1043
  {% endif %}
1004
1044
  ```
1005
1045
 
1006
- ### Additional Exports
1007
-
1008
- The plugin also exports the following utility functions for advanced usage:
1046
+ ### Symlinked Configuration Files
1009
1047
 
1010
- - `transformAutoRaw(content)`: The transform function used by `mdAutoRawTags` preprocessor. Can be used programmatically to wrap Nunjucks syntax with raw tags.
1011
- - `transformNl2br(content)`: The transform function used by `mdAutoNl2br` preprocessor. Can be used programmatically to convert `\n` sequences to `<br>` tags.
1012
- - `isPlainUrlText(linkText, domain)`: Helper function that checks if link text looks like a plain URL or domain.
1013
- - `cleanLinkText(linkText, domain)`: Helper function that cleans link text by removing protocol, domain, and leading slash.
1014
- - `buildFaviconLink(attrs, domain, text)`: Helper function that builds HTML for a link with favicon.
1015
- - `transformLink(match, attrs, url, linkText)`: The transform function used by `mdAutoLinkFavicons` that transforms a single link to include a favicon.
1016
- - `merge(first, ...rest)`: The core merge function used by the `merge` filter. Can be used programmatically to merge arrays or objects.
1017
- - `removeTag(html, tagName)`: The core function used by the `remove_tag` filter. Can be used programmatically to remove HTML tags from content.
1018
- - `iff(trueValue, condition, falseValue)`: The core conditional function used by the `if` filter. Can be used programmatically as a ternary operator.
1019
- - `attrConcat(obj, attr, values)`: The core function used by the `attr_concat` filter. Can be used programmatically to concatenate values to an attribute array.
1048
+ The package includes pre-configured starter files in `node_modules/@anydigital/eleventy-bricks/src/` that you can symlink to your project for quick setup:
1020
1049
 
1021
- ## Starter Configuration Files
1050
+ Benefits of Symlinking:
1022
1051
 
1023
- The package includes pre-configured starter files in `node_modules/@anydigital/eleventy-bricks/src/` that you can symlink to your project for quick setup:
1052
+ - **Always up-to-date**: Configuration automatically updates when you upgrade the package
1053
+ - **Less maintenance**: No need to manually sync configuration changes
1054
+ - **Quick setup**: Get started immediately with best-practice configurations
1055
+ - **Easy customization**: Override specific settings by creating your own config that imports from the symlinked version
1024
1056
 
1025
- ### Available Starter Files
1057
+ If you prefer to customize the configurations extensively, you can copy the files instead.
1026
1058
 
1027
1059
  #### eleventy.config.js
1028
1060
 
@@ -1030,6 +1062,7 @@ A fully-configured Eleventy config file with:
1030
1062
 
1031
1063
  - All eleventy-bricks plugins enabled
1032
1064
  - Eleventy Navigation plugin
1065
+ - Table of Contents plugin (conditionally loaded if installed)
1033
1066
  - Markdown-it with anchors and attributes
1034
1067
  - YAML data support
1035
1068
  - CLI input directory support
@@ -1041,6 +1074,16 @@ A fully-configured Eleventy config file with:
1041
1074
  npm install @11ty/eleventy-navigation markdown-it markdown-it-anchor markdown-it-attrs js-yaml minimist
1042
1075
  ```
1043
1076
 
1077
+ **Optional dependencies:**
1078
+
1079
+ ```bash
1080
+ # For the fetch filter
1081
+ npm install @11ty/eleventy-fetch
1082
+
1083
+ # For table of contents generation
1084
+ npm install @uncenter/eleventy-plugin-toc
1085
+ ```
1086
+
1044
1087
  **Symlink to your project:**
1045
1088
 
1046
1089
  ```bash
@@ -1058,25 +1101,6 @@ mkdir -p admin
1058
1101
  ln -s ../node_modules/@anydigital/eleventy-bricks/src/admin/index.html admin/index.html
1059
1102
  ```
1060
1103
 
1061
- ### Benefits of Symlinking
1062
-
1063
- - **Always up-to-date**: Configuration automatically updates when you upgrade the package
1064
- - **Less maintenance**: No need to manually sync configuration changes
1065
- - **Quick setup**: Get started immediately with best-practice configurations
1066
- - **Easy customization**: Override specific settings by creating your own config that imports from the symlinked version
1067
-
1068
- ### Alternative: Copy Files
1069
-
1070
- If you prefer to customize the configurations extensively, you can copy the files instead:
1071
-
1072
- ```bash
1073
- cp node_modules/@anydigital/eleventy-bricks/src/eleventy.config.js .
1074
- mkdir -p admin
1075
- cp node_modules/@anydigital/eleventy-bricks/src/admin/index.html admin/
1076
- ```
1077
-
1078
- ## Development Workflow Setup
1079
-
1080
1104
  ### Using the `do` Folder Pattern
1081
1105
 
1082
1106
  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.
@@ -1137,68 +1161,3 @@ npm run build
1137
1161
  - **Reusable workflows**: Update scripts by upgrading the package
1138
1162
  - **Workspace isolation**: Scripts run in their own workspace context
1139
1163
  - **Easy maintenance**: No need to manually maintain build scripts
1140
-
1141
- ## CLI Helper Commands
1142
-
1143
- After installing this package, the `download-files` command becomes available:
1144
-
1145
- ### download-files
1146
-
1147
- A CLI command that downloads external files to your project based on URLs specified in your `package.json`.
1148
-
1149
- **Usage:**
1150
-
1151
- 1. Add a `_downloadFiles` field to your project's `package.json` with URL-to-path mappings:
1152
-
1153
- ```json
1154
- {
1155
- "_downloadFiles": {
1156
- "https://example.com/library.js": "src/vendor/library.js",
1157
- "https://cdn.example.com/styles.css": "public/css/external.css"
1158
- }
1159
- }
1160
- ```
1161
-
1162
- 2. Run the download command:
1163
-
1164
- ```bash
1165
- npx download-files
1166
- ```
1167
-
1168
- **Options:**
1169
-
1170
- - `-o, --output <dir>`: Specify an output directory where all files will be downloaded (relative paths in `_downloadFiles` will be resolved relative to this directory)
1171
-
1172
- ```bash
1173
- # Download all files to a specific directory
1174
- npx download-files --output public
1175
- ```
1176
-
1177
- **Features:**
1178
-
1179
- - Downloads multiple files from external URLs
1180
- - Automatically creates directories if they don't exist
1181
- - Overwrites existing files
1182
- - Continues downloading remaining files even if some fail
1183
- - Provides clear progress and error messages
1184
- - Returns appropriate exit codes for CI/CD integration
1185
-
1186
- **Use Cases:**
1187
-
1188
- - Download third-party libraries and assets
1189
- - Fetch external resources during build processes
1190
- - Keep vendored files up to date
1191
- - Automate dependency downloads that aren't available via npm
1192
-
1193
- ## Requirements
1194
-
1195
- - Node.js >= 18.0.0
1196
- - Eleventy >= 3.0.0
1197
-
1198
- ## License
1199
-
1200
- MIT
1201
-
1202
- ## Contributing
1203
-
1204
- Contributions are welcome! Please feel free to submit a Pull Request.