@anydigital/11ty-bricks 1.0.0-alpha.6 → 1.0.0-alpha.7

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
@@ -22,7 +22,7 @@ import eleventyBricks from "@anydigital/11ty-bricks";
22
22
 
23
23
  export default function(eleventyConfig) {
24
24
  eleventyConfig.addPlugin(eleventyBricks, {
25
- autoRaw: true // Enable autoRaw preprocessor (default: false)
25
+ autoRawPreprocessor: true // Enable autoRaw preprocessor (default: false)
26
26
  });
27
27
 
28
28
  // Your other configuration...
@@ -35,7 +35,7 @@ const eleventyBricks = require("@anydigital/11ty-bricks");
35
35
 
36
36
  module.exports = function(eleventyConfig) {
37
37
  eleventyConfig.addPlugin(eleventyBricks, {
38
- autoRaw: true // Enable autoRaw preprocessor (default: false)
38
+ autoRawPreprocessor: true // Enable autoRaw preprocessor (default: false)
39
39
  });
40
40
 
41
41
  // Your other configuration...
@@ -76,14 +76,18 @@ When using the plugin (Option 1), you can configure which helpers to enable:
76
76
 
77
77
  | Option | Type | Default | Description |
78
78
  |--------|------|---------|-------------|
79
- | `bricksRegistry` | boolean | `false` | Enable the bricksRegistry system for dependency management |
80
- | `autoRaw` | boolean | `false` | Enable the autoRaw preprocessor for Markdown files |
79
+ | `bricks` | boolean | `false` | Enable the bricks system for dependency management |
80
+ | `autoRawPreprocessor` | boolean | `false` | Enable the autoRaw preprocessor for Markdown files |
81
+ | `fragments` | boolean | `false` | Enable the fragment shortcode for including content from fragments |
82
+ | `setAttrFilter` | boolean | `false` | Enable the setAttr filter for overriding object attributes |
83
+ | `byAttrFilter` | boolean | `false` | Enable the byAttr filter for filtering collections by attribute values |
81
84
 
82
85
  **Example:**
83
86
  ```javascript
84
87
  eleventyConfig.addPlugin(eleventyBricks, {
85
- bricksRegistry: true,
86
- autoRaw: true
88
+ bricks: true,
89
+ autoRawPreprocessor: true,
90
+ byAttrFilter: true
87
91
  });
88
92
  ```
89
93
 
@@ -120,13 +124,15 @@ export default function(eleventyConfig) {
120
124
  }
121
125
  ```
122
126
 
123
- 2. Add the `bricksRegistry` shortcode in your base template (typically in the `<head>` section):
127
+ 2. Add the `bricksDependencies` shortcode in your base template (typically in the `<head>` section):
124
128
 
125
129
  ```njk
126
130
  <head>
127
131
  <meta charset="UTF-8">
128
132
  <title>My Site</title>
129
- {% bricksRegistry %}
133
+ {% bricksDependencies [
134
+ ... (global dependencies can be set here) ...
135
+ ] %}
130
136
  <!-- Other head content -->
131
137
  </head>
132
138
  ```
@@ -209,84 +215,238 @@ Use {{ variable }} to output variables.
209
215
 
210
216
  Would try to process `{{ variable }}` as a template variable. With `autoRaw`, it displays exactly as written.
211
217
 
212
- ## Available Bricks (Components)
218
+ ### fragment
213
219
 
214
- ### Navigation Macro (`_nav.njk`)
220
+ A shortcode that includes content from fragment files stored in the `_fragments` directory. The content will be processed by the template engine.
215
221
 
216
- A reusable Nunjucks macro for rendering navigation menus with proper accessibility attributes. This macro works seamlessly with the [11ty Navigation Plugin](https://www.11ty.dev/docs/plugins/navigation/).
222
+ **Why use this?**
223
+
224
+ Fragments allow you to organize reusable content snippets in a dedicated directory and include them in your templates. This is useful for:
225
+ - Reusable content blocks
226
+ - Shared template sections
227
+ - Component-like content organization
217
228
 
218
229
  **Usage:**
219
230
 
220
- 1. Import the macro in your template:
231
+ 1. Enable `fragment` in your Eleventy config:
221
232
 
222
- ```njk
223
- {% from "bricks/_nav.njk" import render as renderNav %}
233
+ ```javascript
234
+ import { fragment } from "@anydigital/11ty-bricks";
235
+
236
+ export default function(eleventyConfig) {
237
+ fragment(eleventyConfig);
238
+ // Or use as plugin:
239
+ // eleventyConfig.addPlugin(eleventyBricks, { fragments: true });
240
+ }
241
+ ```
242
+
243
+ 2. Create fragment files in the `_fragments` directory (relative to your input directory):
244
+
245
+ ```
246
+ your-project/
247
+ _fragments/
248
+ header.njk
249
+ footer.njk
250
+ callout.md
224
251
  ```
225
252
 
226
- 2. Call the macro with your navigation data:
253
+ 3. Use the `fragment` shortcode in your templates:
227
254
 
228
255
  ```njk
229
- {{ renderNav(collections.all | eleventyNavigation, page) }}
256
+ {% fragment "header.njk" %}
257
+
258
+ <main>
259
+ <!-- Your content -->
260
+ </main>
261
+
262
+ {% fragment "footer.njk" %}
230
263
  ```
231
264
 
232
265
  **Parameters:**
233
266
 
234
- - `navPages`: Array of navigation entries (typically from `eleventyNavigation` filter)
235
- - `curPage`: Current page object (use Eleventy's `page` variable)
267
+ - `path`: The path to the fragment file relative to the `_fragments` directory
236
268
 
237
269
  **Features:**
238
270
 
239
- - Renders a semantic `<nav>` element
240
- - Automatically adds `aria-current="page"` to the current page link for accessibility
241
- - Clean, minimal markup ready for styling
242
- - Works with nested navigation structures from the 11ty Navigation Plugin
271
+ - Reads files from `_fragments` directory in your input directory
272
+ - Content is processed by the template engine
273
+ - Supports any template language that Eleventy supports
274
+ - Shows helpful error comment if fragment is not found
275
+
276
+ **Example:**
243
277
 
244
- **Example Output:**
278
+ Create `_fragments/callout.njk`:
279
+ ```njk
280
+ <div class="callout callout-{{ type | default('info') }}">
281
+ {{ content }}
282
+ </div>
283
+ ```
245
284
 
246
- ```html
247
- <nav>
248
- <a href="/">Home</a>
249
- <a href="/about/">About</a>
250
- <a href="/contact/" aria-current="page">Contact</a>
251
- </nav>
285
+ Use it in your template:
286
+ ```njk
287
+ {% set type = "warning" %}
288
+ {% set content = "This is important!" %}
289
+ {% fragment "callout.njk" %}
252
290
  ```
253
291
 
254
- ### Google Tag Manager Macro (`_gtm.njk`)
292
+ ### setAttr
255
293
 
256
- A reusable Nunjucks macro for integrating Google Tag Manager (GTM) into your site. Provides separate macros for the head and body GTM snippets.
294
+ 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.
295
+
296
+ **Why use this?**
297
+
298
+ When working with Eleventy data, you sometimes need to modify an object's properties for a specific use case. The `setAttr` filter provides a clean way to create a modified copy of an object without affecting the original.
257
299
 
258
300
  **Usage:**
259
301
 
260
- 1. Import the macros in your base template:
302
+ 1. Enable `setAttr` in your Eleventy config:
303
+
304
+ ```javascript
305
+ import { setAttr } from "@anydigital/11ty-bricks";
306
+
307
+ export default function(eleventyConfig) {
308
+ setAttr(eleventyConfig);
309
+ // Or use as plugin:
310
+ // eleventyConfig.addPlugin(eleventyBricks, { setAttrFilter: true });
311
+ }
312
+ ```
313
+
314
+ 2. Use the filter in your templates:
261
315
 
262
316
  ```njk
263
- {% import 'bricks/_gtm.njk' as gtm %}
317
+ {# Create a modified version of a page object #}
318
+ {% set modifiedPage = page | setAttr('title', 'New Title') %}
319
+
320
+ <h1>{{ modifiedPage.title }}</h1>
321
+ <p>Original title: {{ page.title }}</p>
264
322
  ```
265
323
 
266
- 2. Call the macros in the appropriate locations:
324
+ **Parameters:**
325
+
326
+ - `obj`: The object to modify
327
+ - `key`: The attribute name to set (string)
328
+ - `value`: The value to set for the attribute (any type)
329
+
330
+ **Returns:**
331
+
332
+ A new object with the specified attribute set to the given value. The original object is not modified.
333
+
334
+ **Features:**
335
+
336
+ - Non-mutating: Creates a new object, leaving the original unchanged
337
+ - Works with any object type
338
+ - Supports any attribute name and value type
339
+ - Can be chained with other filters
340
+
341
+ **Examples:**
267
342
 
268
343
  ```njk
269
- <head>
270
- <!-- Other head content -->
271
- {{ gtm.renderHead('GTM-XXXXXXX') }}
272
- </head>
273
- <body>
274
- {{ gtm.renderBody('GTM-XXXXXXX') }}
275
- <!-- Rest of body content -->
276
- </body>
344
+ {# Override a single attribute #}
345
+ {% set updatedPost = post | setAttr('featured', true) %}
346
+
347
+ {# Chain multiple setAttr filters #}
348
+ {% set modifiedPost = post
349
+ | setAttr('category', 'blog')
350
+ | setAttr('priority', 1)
351
+ %}
352
+
353
+ {# Use in loops #}
354
+ {% for item in collection %}
355
+ {% set enhancedItem = item | setAttr('processed', true) %}
356
+ {# ... use enhancedItem ... #}
357
+ {% endfor %}
358
+ ```
359
+
360
+ ### byAttr
361
+
362
+ 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.
363
+
364
+ **Why use this?**
365
+
366
+ When working with Eleventy collections, you often need to filter items based on front matter data. The `byAttr` filter provides a flexible way to filter by any attribute, with special handling for array attributes (like tags).
367
+
368
+ **Usage:**
369
+
370
+ 1. Enable `byAttr` in your Eleventy config:
371
+
372
+ ```javascript
373
+ import { byAttr } from "@anydigital/11ty-bricks";
374
+
375
+ export default function(eleventyConfig) {
376
+ byAttr(eleventyConfig);
377
+ // Or use as plugin:
378
+ // eleventyConfig.addPlugin(eleventyBricks, { byAttrFilter: true });
379
+ }
380
+ ```
381
+
382
+ 2. Use the filter in your templates:
383
+
384
+ **Filter by exact attribute match:**
385
+ ```njk
386
+ {# Get all posts with category 'blog' #}
387
+ {% set blogPosts = collections.all | byAttr('category', 'blog') %}
388
+
389
+ {% for post in blogPosts %}
390
+ <h2>{{ post.data.title }}</h2>
391
+ {% endfor %}
392
+ ```
393
+
394
+ **Filter by array attribute (tags):**
395
+ ```njk
396
+ {# Get all posts that include 'javascript' tag #}
397
+ {% set jsPosts = collections.all | byAttr('tags', 'javascript') %}
398
+
399
+ {% for post in jsPosts %}
400
+ <h2>{{ post.data.title }}</h2>
401
+ {% endfor %}
277
402
  ```
278
403
 
279
404
  **Parameters:**
280
405
 
281
- Both macros accept the same parameter:
282
- - `gtmId`: Your Google Tag Manager container ID (e.g., `'GTM-XXXXXXX'`)
406
+ - `collection`: The collection to filter (array of items)
407
+ - `attrName`: The attribute name to check (string)
408
+ - `targetValue`: The value to match against (any type)
283
409
 
284
410
  **Features:**
285
411
 
286
- - Separate macros for head and body placement as recommended by Google
287
- - Clean, standard GTM implementation
288
- - Easy to maintain and update across your site
289
- - Works with all GTM features including noscript fallback
412
+ - Works with any attribute in front matter
413
+ - Handles both `item.data.attrName` and `item.attrName` patterns
414
+ - Special handling for array attributes (uses `includes()` check)
415
+ - Returns empty array if collection is invalid
416
+ - Filters out items without the specified attribute
417
+
418
+ **Examples:**
419
+
420
+ Front matter:
421
+ ```yaml
422
+ ---
423
+ title: My Post
424
+ category: blog
425
+ tags: [javascript, tutorial, beginner]
426
+ priority: 1
427
+ ---
428
+ ```
429
+
430
+ Template usage:
431
+ ```njk
432
+ {# Filter by category #}
433
+ {% set blogPosts = collections.all | byAttr('category', 'blog') %}
434
+
435
+ {# Filter by tag (array) #}
436
+ {% set jsTutorials = collections.all | byAttr('tags', 'javascript') %}
437
+
438
+ {# Filter by numeric value #}
439
+ {% set highPriority = collections.all | byAttr('priority', 1) %}
440
+
441
+ {# Chain filters #}
442
+ {% set recentBlogPosts = collections.all | byAttr('category', 'blog') | reverse | limit(5) %}
443
+ ```
444
+
445
+ ### Additional Exports
446
+
447
+ The plugin also exports the following for advanced usage:
448
+
449
+ - `transformAutoRaw(content)`: The transform function used by `autoRaw` preprocessor. Can be used programmatically to wrap Nunjucks syntax with raw tags.
290
450
 
291
451
  ## CLI Helper Commands
292
452
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anydigital/11ty-bricks",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.7",
4
4
  "description": "A collection of helpful utilities and filters for Eleventy (11ty)",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -23,7 +23,7 @@ export function bricksRegistry(eleventyConfig) {
23
23
  });
24
24
 
25
25
  // brick shortcode: registers and renders a brick component
26
- eleventyConfig.addShortcode("brick", function(brickModule) {
26
+ eleventyConfig.addShortcode("brick", function(brickModule, ...args) {
27
27
  const registry = getPageRegistry(this.page);
28
28
 
29
29
  if (!brickModule) return '';
@@ -47,14 +47,14 @@ export function bricksRegistry(eleventyConfig) {
47
47
 
48
48
  // Render the brick using render() macro
49
49
  if (brickModule.render && typeof brickModule.render === 'function') {
50
- return brickModule.render();
50
+ return brickModule.render(...args);
51
51
  }
52
52
 
53
53
  return '';
54
54
  });
55
55
 
56
56
  // bricksRegistry shortcode: outputs placeholder and base dependencies
57
- eleventyConfig.addShortcode("bricksRegistry", function(dependencies = []) {
57
+ eleventyConfig.addShortcode("bricksDependencies", function(dependencies = []) {
58
58
  const registry = getPageRegistry(this.page);
59
59
 
60
60
  // Register root dependencies if provided (categorized later in transform)
package/src/byAttr.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * byAttr filter - Filter collection items by attribute value
3
+ *
4
+ * This filter takes a collection, an attribute name, and a target value,
5
+ * and returns items where the attribute matches the target value.
6
+ * If the attribute is an array, it checks if the array includes the target value.
7
+ *
8
+ * @param {Object} eleventyConfig - The Eleventy configuration object
9
+ */
10
+ export function byAttr(eleventyConfig) {
11
+ eleventyConfig.addFilter("byAttr", function(collection, attrName, targetValue) {
12
+ if (!collection || !Array.isArray(collection)) {
13
+ return [];
14
+ }
15
+
16
+ return collection.filter(item => {
17
+ // Get the attribute value from the item's data
18
+ const attrValue = item?.data?.[attrName] ?? item?.[attrName];
19
+
20
+ // If attribute doesn't exist, skip this item
21
+ if (attrValue === undefined || attrValue === null) {
22
+ return false;
23
+ }
24
+
25
+ // If the attribute is an array, check if it includes the target value
26
+ if (Array.isArray(attrValue)) {
27
+ return attrValue.includes(targetValue);
28
+ }
29
+
30
+ // Otherwise, do a direct comparison
31
+ return attrValue === targetValue;
32
+ });
33
+ });
34
+ }
35
+
@@ -0,0 +1,105 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { byAttr } from './byAttr.js';
4
+
5
+ describe('byAttr filter', () => {
6
+ let filterFn;
7
+
8
+ // Mock eleventyConfig to capture the filter function
9
+ const mockEleventyConfig = {
10
+ addFilter(name, fn) {
11
+ if (name === 'byAttr') {
12
+ filterFn = fn;
13
+ }
14
+ }
15
+ };
16
+
17
+ // Register the filter
18
+ byAttr(mockEleventyConfig);
19
+
20
+ it('should filter items by exact attribute match', () => {
21
+ const collection = [
22
+ { data: { category: 'blog' }, title: 'Post 1' },
23
+ { data: { category: 'news' }, title: 'Post 2' },
24
+ { data: { category: 'blog' }, title: 'Post 3' }
25
+ ];
26
+
27
+ const result = filterFn(collection, 'category', 'blog');
28
+ assert.strictEqual(result.length, 2);
29
+ assert.strictEqual(result[0].title, 'Post 1');
30
+ assert.strictEqual(result[1].title, 'Post 3');
31
+ });
32
+
33
+ it('should filter items when attribute is an array (includes check)', () => {
34
+ const collection = [
35
+ { data: { tags: ['javascript', 'tutorial'] }, title: 'Post 1' },
36
+ { data: { tags: ['python', 'tutorial'] }, title: 'Post 2' },
37
+ { data: { tags: ['javascript', 'advanced'] }, title: 'Post 3' }
38
+ ];
39
+
40
+ const result = filterFn(collection, 'tags', 'javascript');
41
+ assert.strictEqual(result.length, 2);
42
+ assert.strictEqual(result[0].title, 'Post 1');
43
+ assert.strictEqual(result[1].title, 'Post 3');
44
+ });
45
+
46
+ it('should return empty array when collection is not an array', () => {
47
+ const result = filterFn(null, 'category', 'blog');
48
+ assert.strictEqual(result.length, 0);
49
+ });
50
+
51
+ it('should filter out items without the specified attribute', () => {
52
+ const collection = [
53
+ { data: { category: 'blog' }, title: 'Post 1' },
54
+ { data: {}, title: 'Post 2' },
55
+ { data: { category: 'blog' }, title: 'Post 3' }
56
+ ];
57
+
58
+ const result = filterFn(collection, 'category', 'blog');
59
+ assert.strictEqual(result.length, 2);
60
+ });
61
+
62
+ it('should work with attribute directly on item (not in data)', () => {
63
+ const collection = [
64
+ { category: 'blog', title: 'Post 1' },
65
+ { category: 'news', title: 'Post 2' },
66
+ { category: 'blog', title: 'Post 3' }
67
+ ];
68
+
69
+ const result = filterFn(collection, 'category', 'blog');
70
+ assert.strictEqual(result.length, 2);
71
+ });
72
+
73
+ it('should handle mixed data structures', () => {
74
+ const collection = [
75
+ { data: { category: 'blog' }, title: 'Post 1' },
76
+ { category: 'blog', title: 'Post 2' },
77
+ { data: { category: 'news' }, title: 'Post 3' }
78
+ ];
79
+
80
+ const result = filterFn(collection, 'category', 'blog');
81
+ assert.strictEqual(result.length, 2);
82
+ });
83
+
84
+ it('should handle array that does not include target value', () => {
85
+ const collection = [
86
+ { data: { tags: ['python', 'tutorial'] }, title: 'Post 1' },
87
+ { data: { tags: ['ruby', 'guide'] }, title: 'Post 2' }
88
+ ];
89
+
90
+ const result = filterFn(collection, 'tags', 'javascript');
91
+ assert.strictEqual(result.length, 0);
92
+ });
93
+
94
+ it('should handle different value types', () => {
95
+ const collection = [
96
+ { data: { priority: 1 }, title: 'Post 1' },
97
+ { data: { priority: 2 }, title: 'Post 2' },
98
+ { data: { priority: 1 }, title: 'Post 3' }
99
+ ];
100
+
101
+ const result = filterFn(collection, 'priority', 1);
102
+ assert.strictEqual(result.length, 2);
103
+ });
104
+ });
105
+
@@ -0,0 +1,34 @@
1
+ import { readFileSync } from "fs";
2
+ import { join } from "path";
3
+
4
+ /**
5
+ * fragment shortcode - Include content from fragments
6
+ *
7
+ * This shortcode reads a file from the _fragments directory and includes
8
+ * its content. The content will be processed by the template engine.
9
+ *
10
+ * @param {Object} eleventyConfig - The Eleventy configuration object
11
+ */
12
+ export function fragment(eleventyConfig) {
13
+ eleventyConfig.addShortcode("fragment", function(path) {
14
+ // Get the input directory from Eleventy's context
15
+ const inputDir = this.page?.inputPath
16
+ ? join(process.cwd(), eleventyConfig.dir?.input || ".")
17
+ : process.cwd();
18
+
19
+ // Construct the full path to the fragment file
20
+ const fragmentPath = join(inputDir, "_fragments", path);
21
+
22
+ try {
23
+ // Read the fragment file
24
+ const content = readFileSync(fragmentPath, "utf8");
25
+
26
+ // Return content to be processed by the template engine
27
+ return content;
28
+ } catch (error) {
29
+ console.error(`Error reading fragment at ${fragmentPath}:`, error.message);
30
+ return `<!-- Fragment not found: ${path} -->`;
31
+ }
32
+ });
33
+ }
34
+
package/src/index.cjs CHANGED
@@ -18,3 +18,15 @@ module.exports.autoRaw = async function(eleventyConfig) {
18
18
  const { autoRaw } = await import('./index.js');
19
19
  return autoRaw(eleventyConfig);
20
20
  };
21
+ module.exports.fragment = async function(eleventyConfig) {
22
+ const { fragment } = await import('./index.js');
23
+ return fragment(eleventyConfig);
24
+ };
25
+ module.exports.setAttr = async function(eleventyConfig) {
26
+ const { setAttr } = await import('./index.js');
27
+ return setAttr(eleventyConfig);
28
+ };
29
+ module.exports.byAttr = async function(eleventyConfig) {
30
+ const { byAttr } = await import('./index.js');
31
+ return byAttr(eleventyConfig);
32
+ };
package/src/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { bricksRegistry } from "./bricksRegistry.js";
2
2
  import { autoRaw } from "./autoRaw.js";
3
+ import { fragment } from "./fragment.js";
4
+ import { setAttr } from "./setAttr.js";
5
+ import { byAttr } from "./byAttr.js";
3
6
 
4
7
  /**
5
8
  * 11ty Bricks Plugin
@@ -9,18 +12,33 @@ import { autoRaw } from "./autoRaw.js";
9
12
  *
10
13
  * @param {Object} eleventyConfig - The Eleventy configuration object
11
14
  * @param {Object} options - Plugin options
12
- * @param {boolean} options.bricksRegistry - Enable bricksRegistry (default: false)
13
- * @param {boolean} options.autoRaw - Enable autoRaw preprocessor (default: false)
15
+ * @param {boolean} options.bricks - Enable bricks system with dependencies injection (default: false)
16
+ * @param {boolean} options.autoRawPreprocessor - Enable autoRaw preprocessor (default: false)
17
+ * @param {boolean} options.fragments - Enable fragment shortcode (default: false)
18
+ * @param {boolean} options.setAttrFilter - Enable setAttr filter (default: false)
19
+ * @param {boolean} options.byAttrFilter - Enable byAttr filter (default: false)
14
20
  */
15
21
  export default function eleventyBricksPlugin(eleventyConfig, options = {}) {
16
- if (options.bricksRegistry) {
22
+ if (options.bricks) {
17
23
  bricksRegistry(eleventyConfig);
18
24
  }
19
- if (options.autoRaw) {
25
+ if (options.autoRawPreprocessor) {
20
26
  autoRaw(eleventyConfig);
21
27
  }
28
+ if (options.fragments) {
29
+ fragment(eleventyConfig);
30
+ }
31
+ if (options.setAttrFilter) {
32
+ setAttr(eleventyConfig);
33
+ }
34
+ if (options.byAttrFilter) {
35
+ byAttr(eleventyConfig);
36
+ }
22
37
  }
23
38
 
24
39
  // Export individual helpers for granular usage
25
40
  export { bricksRegistry };
26
41
  export { autoRaw };
42
+ export { fragment };
43
+ export { setAttr };
44
+ export { byAttr };
package/src/setAttr.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * setAttr filter - Override an attribute and return the object
3
+ *
4
+ * This filter takes an object, a key, and a value, and returns a new object
5
+ * with the specified attribute set to the given value.
6
+ *
7
+ * @param {Object} eleventyConfig - The Eleventy configuration object
8
+ */
9
+ export function setAttr(eleventyConfig) {
10
+ eleventyConfig.addFilter("setAttr", function(obj, key, value) {
11
+ return {
12
+ ...obj,
13
+ [key]: value
14
+ };
15
+ });
16
+ }
17
+
@@ -1,16 +0,0 @@
1
- {% macro renderHead(gtmId) %}
2
- <!-- Google Tag Manager -->
3
- <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
4
- new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
5
- j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
6
- 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
7
- })(window,document,'script','dataLayer','{{ gtmId }}');</script>
8
- <!-- End Google Tag Manager -->
9
- {% endmacro %}
10
-
11
- {% macro renderBody(gtmId) %}
12
- <!-- Google Tag Manager (noscript) -->
13
- <noscript><iframe src="https://www.googletagmanager.com/ns.html?id={{ gtmId }}"
14
- height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
15
- <!-- End Google Tag Manager (noscript) -->
16
- {% endmacro %}
@@ -1,10 +0,0 @@
1
- {% macro render(navPages, curPage) %}
2
- {# https://www.11ty.dev/docs/plugins/navigation/#bring-your-own-html-render-the-menu-items-manually #}
3
- <nav>
4
- {%- for entry in navPages %}
5
- <a href="{{ entry.url }}" {{ 'aria-current="page"' | safe if entry.url == curPage.url }}>
6
- {{- entry.title -}}
7
- </a>
8
- {%- endfor %}
9
- </nav>
10
- {% endmacro %}