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