@anydigital/eleventy-bricks 0.25.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,9 +78,9 @@ 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);
@@ -101,9 +101,9 @@ export default function (eleventyConfig) {
101
101
  const {
102
102
  mdAutoRawTags,
103
103
  mdAutoNl2br,
104
- mdAutoLinkFavicons,
105
- setAttrFilter,
106
- whereInFilter,
104
+ autoLinkFavicons,
105
+ attrSetFilter,
106
+ attrIncludesFilter,
107
107
  mergeFilter,
108
108
  removeTagFilter,
109
109
  ifFilter,
@@ -115,9 +115,9 @@ const {
115
115
  module.exports = async function (eleventyConfig) {
116
116
  await mdAutoRawTags(eleventyConfig);
117
117
  await mdAutoNl2br(eleventyConfig);
118
- await mdAutoLinkFavicons(eleventyConfig);
119
- await setAttrFilter(eleventyConfig);
120
- await whereInFilter(eleventyConfig);
118
+ await autoLinkFavicons(eleventyConfig);
119
+ await attrSetFilter(eleventyConfig);
120
+ await attrIncludesFilter(eleventyConfig);
121
121
  await mergeFilter(eleventyConfig);
122
122
  await removeTagFilter(eleventyConfig);
123
123
  await ifFilter(eleventyConfig);
@@ -138,18 +138,18 @@ module.exports = async function (eleventyConfig) {
138
138
 
139
139
  When using the plugin (Option 1), you can configure which helpers to enable:
140
140
 
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
- | `mdAutoLinkFavicons` | boolean | `false` | Enable the mdAutoLinkFavicons 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) |
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) |
148
148
 
149
149
  **Available filter names for the `filters` array:**
150
150
 
151
- - `'attr'` - Override object attributes
152
- - `'where_in'` - Filter collections by attribute values
151
+ - `'attr_set'` - Override object attributes
152
+ - `'attr_includes'` - Filter collections by attribute values
153
153
  - `'merge'` - Merge arrays or objects
154
154
  - `'remove_tag'` - Remove HTML elements from content
155
155
  - `'if'` - Inline conditional/ternary operator
@@ -162,188 +162,80 @@ When using the plugin (Option 1), you can configure which helpers to enable:
162
162
  eleventyConfig.addPlugin(eleventyBricks, {
163
163
  mdAutoRawTags: true,
164
164
  mdAutoNl2br: true,
165
- mdAutoLinkFavicons: true,
165
+ autoLinkFavicons: true,
166
166
  siteData: true,
167
- filters: ["attr", "where_in", "merge", "remove_tag", "if", "attr_concat", "fetch"],
167
+ filters: ["attr_set", "attr_includes", "merge", "remove_tag", "if", "attr_concat", "fetch"],
168
168
  });
169
169
  ```
170
170
 
171
- ## Available 11ty Helpers
172
-
173
- ### mdAutoRawTags
174
-
175
- Prevents Nunjucks syntax from being processed in Markdown files by automatically wrapping `{{`, `}}`, `{%`, and `%}` with `{% raw %}` tags.
176
-
177
- **Why use this?**
178
-
179
- 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.
180
-
181
- **Usage:**
182
-
183
- 1. Enable `mdAutoRawTags` in your Eleventy config:
184
-
185
- ```javascript
186
- import { mdAutoRawTags } from "@anydigital/eleventy-bricks";
187
-
188
- export default function (eleventyConfig) {
189
- mdAutoRawTags(eleventyConfig);
190
- // Or use as plugin:
191
- // eleventyConfig.addPlugin(eleventyBricks, { mdAutoRawTags: true });
192
- }
193
- ```
194
-
195
- **Example:**
196
-
197
- Before `mdAutoRawTags`, writing this in Markdown:
198
-
199
- ```markdown
200
- Use {{ variable }} to output variables.
201
- ```
202
-
203
- Would try to process `{{ variable }}` as a template variable. With `mdAutoRawTags`, it displays exactly as written.
204
-
205
- ### mdAutoNl2br
206
-
207
- 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.
208
-
209
- **Why use this?**
210
-
211
- 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.
212
-
213
- **Usage:**
214
-
215
- 1. Enable `mdAutoNl2br` in your Eleventy config:
216
-
217
- ```javascript
218
- import { mdAutoNl2br } from "@anydigital/eleventy-bricks";
219
-
220
- export default function (eleventyConfig) {
221
- mdAutoNl2br(eleventyConfig);
222
- // Or use as plugin:
223
- // eleventyConfig.addPlugin(eleventyBricks, { mdAutoNl2br: true });
224
- }
225
- ```
226
-
227
- **Example:**
228
-
229
- In your Markdown file:
230
-
231
- ```markdown
232
- | Column 1 | Column 2 |
233
- | ---------------------- | --------------------------------- |
234
- | Line 1\nLine 2\nLine 3 | Another cell\nWith multiple lines |
235
- ```
236
-
237
- Will render as:
238
-
239
- ```html
240
- <td>Line 1<br />Line 2<br />Line 3</td>
241
- <td>Another cell<br />With multiple lines</td>
242
- ```
243
-
244
- **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.
245
-
246
- ### mdAutoLinkFavicons
247
-
248
- 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.
249
-
250
- **Why use this?**
251
-
252
- 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.
253
-
254
- **Usage:**
255
-
256
- 1. Enable `mdAutoLinkFavicons` in your Eleventy config:
257
-
258
- ```javascript
259
- import { mdAutoLinkFavicons } from "@anydigital/eleventy-bricks";
260
-
261
- export default function (eleventyConfig) {
262
- mdAutoLinkFavicons(eleventyConfig);
263
- // Or use as plugin:
264
- // eleventyConfig.addPlugin(eleventyBricks, { mdAutoLinkFavicons: true });
265
- }
266
- ```
267
-
268
- **How it works:**
269
-
270
- The transform:
271
-
272
- 1. Scans all HTML output files for `<a>` tags
273
- 2. Checks if the link text appears to be a plain URL or domain
274
- 3. Extracts the domain from the URL
275
- 4. Removes the domain from the link text (keeping only the path)
276
- 5. Adds a favicon image from Google's favicon service inline with the remaining text
171
+ ### Additional Exports
277
172
 
278
- **Example:**
173
+ The plugin also exports the following utility functions for advanced usage:
279
174
 
280
- Before transformation:
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.
281
188
 
282
- ```html
283
- <a href="https://github.com/anydigital/eleventy-bricks">https://github.com/anydigital/eleventy-bricks</a>
284
- ```
189
+ <!--TRICKS-->
285
190
 
286
- After transformation:
191
+ ## Tricks from [Eleventy Bricks](https://github.com/anydigital/eleventy-bricks) {#eleventy-bricks}
287
192
 
288
- ```html
289
- <a href="https://github.com/anydigital/eleventy-bricks" class="whitespace-nowrap" target="_blank">
290
- <i><img src="https://www.google.com/s2/favicons?domain=github.com&sz=32" /></i>
291
- <span>/anydigital/eleventy-bricks</span>
292
- </a>
293
- ```
193
+ ### Filters
294
194
 
295
- **Rules:**
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) |
296
214
 
297
- - Only applies to links where the text looks like a plain URL (contains the domain or starts with `http://`/`https://`)
298
- - Removes the protocol and domain from the display text
299
- - Removes the trailing slash from the display text
300
- - Only applies if at least 3 characters remain after removing the domain (to avoid showing favicons for bare domain links)
301
- - Uses Google's favicon service at `https://www.google.com/s2/favicons?domain=DOMAIN&sz=32`
302
- - Adds `target="_blank"` to the transformed links (only if not already present)
303
- - Adds `whitespace-nowrap` class to the link
304
- - Wraps the link text in a `<span>` element
305
- - The favicon is wrapped in an `<i>` tag for easy styling
215
+ Ref:
306
216
 
307
- **Styling:**
217
+ - https://mozilla.github.io/nunjucks/templating.html#builtin-filters
218
+ - https://shopify.github.io/liquid/
308
219
 
309
- You can style the favicon icons with CSS:
310
-
311
- ```css
312
- /* Style the favicon wrapper */
313
- a i {
314
- display: inline-block;
315
- margin-right: 0.25em;
316
- }
317
-
318
- /* Style the favicon image */
319
- a i img {
320
- width: 16px;
321
- height: 16px;
322
- vertical-align: middle;
323
- }
324
- ```
325
-
326
- **Note:** This transform only processes HTML output files (those ending in `.html`). It does not modify the original content files.
327
-
328
- ### attr
220
+ #### `attr_set`
329
221
 
330
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.
331
223
 
332
224
  **Why use this?**
333
225
 
334
- 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.
335
227
 
336
228
  **Usage:**
337
229
 
338
- 1. Enable the `attr` filter in your Eleventy config:
230
+ 1. Enable the `attr_set` filter in your Eleventy config:
339
231
 
340
232
  ```javascript
341
- import { setAttrFilter } from "@anydigital/eleventy-bricks";
233
+ import { attrSetFilter } from "@anydigital/eleventy-bricks";
342
234
 
343
235
  export default function (eleventyConfig) {
344
- setAttrFilter(eleventyConfig);
236
+ attrSetFilter(eleventyConfig);
345
237
  // Or use as plugin:
346
- // eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr'] });
238
+ // eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr_set'] });
347
239
  }
348
240
  ```
349
241
 
@@ -351,7 +243,7 @@ export default function (eleventyConfig) {
351
243
 
352
244
  ```njk
353
245
  {# Create a modified version of a page object #}
354
- {% set modifiedPage = page | attr('title', 'New Title') %}
246
+ {% set modifiedPage = page | attr_set('title', 'New Title') %}
355
247
 
356
248
  <h1>{{ modifiedPage.title }}</h1>
357
249
  <p>Original title: {{ page.title }}</p>
@@ -378,61 +270,50 @@ A new object with the specified attribute set to the given value. The original o
378
270
 
379
271
  ```njk
380
272
  {# Override a single attribute #}
381
- {% set updatedPost = post | attr('featured', true) %}
273
+ {% set updatedPost = post | attr_set('featured', true) %}
382
274
 
383
- {# Chain multiple attr filters #}
275
+ {# Chain multiple attr_set filters #}
384
276
  {% set modifiedPost = post
385
- | attr('category', 'blog')
386
- | attr('priority', 1)
277
+ | attr_set('category', 'blog')
278
+ | attr_set('priority', 1)
387
279
  %}
388
280
 
389
281
  {# Use in loops #}
390
282
  {% for item in collection %}
391
- {% set enhancedItem = item | attr('processed', true) %}
283
+ {% set enhancedItem = item | attr_set('processed', true) %}
392
284
  {# ... use enhancedItem ... #}
393
285
  {% endfor %}
394
286
  ```
395
287
 
396
- ### where_in
288
+ #### `attr_includes`
397
289
 
398
- 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.
399
291
 
400
292
  **Why use this?**
401
293
 
402
- 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.
403
295
 
404
296
  **Usage:**
405
297
 
406
- 1. Enable the `where_in` filter in your Eleventy config:
298
+ 1. Enable the `attr_includes` filter in your Eleventy config:
407
299
 
408
300
  ```javascript
409
- import { whereInFilter } from "@anydigital/eleventy-bricks";
301
+ import { attrIncludesFilter } from "@anydigital/eleventy-bricks";
410
302
 
411
303
  export default function (eleventyConfig) {
412
- whereInFilter(eleventyConfig);
304
+ attrIncludesFilter(eleventyConfig);
413
305
  // Or use as plugin:
414
- // eleventyConfig.addPlugin(eleventyBricks, { filters: ['where_in'] });
306
+ // eleventyConfig.addPlugin(eleventyBricks, { filters: ['attr_includes'] });
415
307
  }
416
308
  ```
417
309
 
418
310
  2. Use the filter in your templates:
419
311
 
420
- **Filter by exact attribute match:**
421
-
422
- ```njk
423
- {# Get all posts with category 'blog' #}
424
- {% set blogPosts = collections.all | where_in('data.category', 'blog') %}
425
-
426
- {% for post in blogPosts %}
427
- <h2>{{ post.data.title }}</h2>
428
- {% endfor %}
429
- ```
430
-
431
312
  **Filter by array attribute (tags):**
432
313
 
433
314
  ```njk
434
315
  {# Get all posts that include 'javascript' tag #}
435
- {% set jsPosts = collections.all | where_in('data.tags', 'javascript') %}
316
+ {% set jsPosts = collections.all | attr_includes('data.tags', 'javascript') %}
436
317
 
437
318
  {% for post in jsPosts %}
438
319
  <h2>{{ post.data.title }}</h2>
@@ -443,15 +324,14 @@ export default function (eleventyConfig) {
443
324
 
444
325
  - `collection`: The collection to filter (array of items)
445
326
  - `attrName`: The attribute name to check (string, supports dot notation for nested properties)
446
- - `targetValue`: The value to match against (any type)
327
+ - `targetValue`: The value to check for in the array (any type)
447
328
 
448
329
  **Features:**
449
330
 
450
- - Works with any attribute in front matter
451
- - Supports dot notation for nested properties (e.g., `'data.tags'`, `'data.author.name'`)
452
- - 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'`)
453
333
  - Returns empty array if collection is invalid
454
- - Filters out items without the specified attribute
334
+ - Filters out items where the specified attribute is not an array or doesn't exist
455
335
 
456
336
  **Examples:**
457
337
 
@@ -469,20 +349,17 @@ priority: 1
469
349
  Template usage:
470
350
 
471
351
  ```njk
472
- {# Filter by category (using dot notation for nested properties) #}
473
- {% set blogPosts = collections.all | where_in('data.category', 'blog') %}
474
-
475
- {# Filter by tag (array) #}
476
- {% 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') %}
477
354
 
478
- {# Filter by numeric value #}
479
- {% 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) %}
480
357
 
481
358
  {# Chain filters #}
482
- {% 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) %}
483
360
  ```
484
361
 
485
- ### merge
362
+ #### `merge`
486
363
 
487
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.
488
365
 
@@ -549,8 +426,8 @@ export default function (eleventyConfig) {
549
426
 
550
427
  ```njk
551
428
  {# Combine featured and regular posts #}
552
- {% set featuredPosts = collections.all | where_in('data.featured', true) %}
553
- {% 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) %}
554
431
  {% set allPosts = featuredPosts | merge(regularPosts) %}
555
432
 
556
433
  {# Merge page metadata with defaults #}
@@ -570,7 +447,7 @@ export default function (eleventyConfig) {
570
447
  {% set config = defaults | merge(siteConfig, pageConfig, userPrefs) %}
571
448
  ```
572
449
 
573
- ### remove_tag
450
+ #### `remove_tag`
574
451
 
575
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.
576
453
 
@@ -643,7 +520,7 @@ export default function (eleventyConfig) {
643
520
 
644
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.
645
522
 
646
- ### if
523
+ #### `if`
647
524
 
648
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.
649
526
 
@@ -718,7 +595,7 @@ export default function (eleventyConfig) {
718
595
  {% set cssClass = 'featured' | if: post.featured | upper %}
719
596
  ```
720
597
 
721
- ### attr_concat
598
+ #### `attr_concat`
722
599
 
723
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.
724
601
 
@@ -800,7 +677,7 @@ A new object with the specified attribute containing the combined unique array.
800
677
  {% endfor %}
801
678
  ```
802
679
 
803
- ### fetch
680
+ #### `fetch`
804
681
 
805
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.
806
683
 
@@ -933,7 +810,164 @@ your-project/
933
810
 
934
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.
935
812
 
936
- ### 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
937
971
 
938
972
  Adds global site data to your Eleventy project, providing commonly needed values that can be accessed in all templates.
939
973
 
@@ -1009,26 +1043,18 @@ export default function (eleventyConfig) {
1009
1043
  {% endif %}
1010
1044
  ```
1011
1045
 
1012
- ### Additional Exports
1013
-
1014
- The plugin also exports the following utility functions for advanced usage:
1046
+ ### Symlinked Configuration Files
1015
1047
 
1016
- - `transformAutoRaw(content)`: The transform function used by `mdAutoRawTags` preprocessor. Can be used programmatically to wrap Nunjucks syntax with raw tags.
1017
- - `transformNl2br(content)`: The transform function used by `mdAutoNl2br` preprocessor. Can be used programmatically to convert `\n` sequences to `<br>` tags.
1018
- - `isPlainUrlText(linkText, domain)`: Helper function that checks if link text looks like a plain URL or domain.
1019
- - `cleanLinkText(linkText, domain)`: Helper function that cleans link text by removing protocol, domain, and leading slash.
1020
- - `buildFaviconLink(attrs, domain, text)`: Helper function that builds HTML for a link with favicon.
1021
- - `transformLink(match, attrs, url, linkText)`: The transform function used by `mdAutoLinkFavicons` that transforms a single link to include a favicon.
1022
- - `merge(first, ...rest)`: The core merge function used by the `merge` filter. Can be used programmatically to merge arrays or objects.
1023
- - `removeTag(html, tagName)`: The core function used by the `remove_tag` filter. Can be used programmatically to remove HTML tags from content.
1024
- - `iff(trueValue, condition, falseValue)`: The core conditional function used by the `if` filter. Can be used programmatically as a ternary operator.
1025
- - `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:
1026
1049
 
1027
- ## Starter Configuration Files
1050
+ Benefits of Symlinking:
1028
1051
 
1029
- 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
1030
1056
 
1031
- ### Available Starter Files
1057
+ If you prefer to customize the configurations extensively, you can copy the files instead.
1032
1058
 
1033
1059
  #### eleventy.config.js
1034
1060
 
@@ -1075,25 +1101,6 @@ mkdir -p admin
1075
1101
  ln -s ../node_modules/@anydigital/eleventy-bricks/src/admin/index.html admin/index.html
1076
1102
  ```
1077
1103
 
1078
- ### Benefits of Symlinking
1079
-
1080
- - **Always up-to-date**: Configuration automatically updates when you upgrade the package
1081
- - **Less maintenance**: No need to manually sync configuration changes
1082
- - **Quick setup**: Get started immediately with best-practice configurations
1083
- - **Easy customization**: Override specific settings by creating your own config that imports from the symlinked version
1084
-
1085
- ### Alternative: Copy Files
1086
-
1087
- If you prefer to customize the configurations extensively, you can copy the files instead:
1088
-
1089
- ```bash
1090
- cp node_modules/@anydigital/eleventy-bricks/src/eleventy.config.js .
1091
- mkdir -p admin
1092
- cp node_modules/@anydigital/eleventy-bricks/src/admin/index.html admin/
1093
- ```
1094
-
1095
- ## Development Workflow Setup
1096
-
1097
1104
  ### Using the `do` Folder Pattern
1098
1105
 
1099
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.
@@ -1154,68 +1161,3 @@ npm run build
1154
1161
  - **Reusable workflows**: Update scripts by upgrading the package
1155
1162
  - **Workspace isolation**: Scripts run in their own workspace context
1156
1163
  - **Easy maintenance**: No need to manually maintain build scripts
1157
-
1158
- ## CLI Helper Commands
1159
-
1160
- After installing this package, the `download-files` command becomes available:
1161
-
1162
- ### download-files
1163
-
1164
- A CLI command that downloads external files to your project based on URLs specified in your `package.json`.
1165
-
1166
- **Usage:**
1167
-
1168
- 1. Add a `_downloadFiles` field to your project's `package.json` with URL-to-path mappings:
1169
-
1170
- ```json
1171
- {
1172
- "_downloadFiles": {
1173
- "https://example.com/library.js": "src/vendor/library.js",
1174
- "https://cdn.example.com/styles.css": "public/css/external.css"
1175
- }
1176
- }
1177
- ```
1178
-
1179
- 2. Run the download command:
1180
-
1181
- ```bash
1182
- npx download-files
1183
- ```
1184
-
1185
- **Options:**
1186
-
1187
- - `-o, --output <dir>`: Specify an output directory where all files will be downloaded (relative paths in `_downloadFiles` will be resolved relative to this directory)
1188
-
1189
- ```bash
1190
- # Download all files to a specific directory
1191
- npx download-files --output public
1192
- ```
1193
-
1194
- **Features:**
1195
-
1196
- - Downloads multiple files from external URLs
1197
- - Automatically creates directories if they don't exist
1198
- - Overwrites existing files
1199
- - Continues downloading remaining files even if some fail
1200
- - Provides clear progress and error messages
1201
- - Returns appropriate exit codes for CI/CD integration
1202
-
1203
- **Use Cases:**
1204
-
1205
- - Download third-party libraries and assets
1206
- - Fetch external resources during build processes
1207
- - Keep vendored files up to date
1208
- - Automate dependency downloads that aren't available via npm
1209
-
1210
- ## Requirements
1211
-
1212
- - Node.js >= 18.0.0
1213
- - Eleventy >= 3.0.0
1214
-
1215
- ## License
1216
-
1217
- MIT
1218
-
1219
- ## Contributing
1220
-
1221
- Contributions are welcome! Please feel free to submit a Pull Request.