@anydigital/11ty-bricks 1.0.0-alpha.4 → 1.0.0-alpha.5
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 +146 -2
- package/package.json +1 -1
- package/src/bricks/_gtm.njk +16 -0
- package/src/bricksRegistry.js +125 -0
- package/src/index.cjs +4 -1
- package/src/index.js +7 -5
package/README.md
CHANGED
|
@@ -48,9 +48,10 @@ Import only the specific helpers you need without using the plugin:
|
|
|
48
48
|
|
|
49
49
|
**ES Modules:**
|
|
50
50
|
```javascript
|
|
51
|
-
import { autoRaw } from "@anydigital/11ty-bricks";
|
|
51
|
+
import { bricksRegistry, autoRaw } from "@anydigital/11ty-bricks";
|
|
52
52
|
|
|
53
53
|
export default function(eleventyConfig) {
|
|
54
|
+
bricksRegistry(eleventyConfig);
|
|
54
55
|
autoRaw(eleventyConfig);
|
|
55
56
|
|
|
56
57
|
// Your other configuration...
|
|
@@ -59,9 +60,10 @@ export default function(eleventyConfig) {
|
|
|
59
60
|
|
|
60
61
|
**CommonJS:**
|
|
61
62
|
```javascript
|
|
62
|
-
const { autoRaw } = require("@anydigital/11ty-bricks");
|
|
63
|
+
const { bricksRegistry, autoRaw } = require("@anydigital/11ty-bricks");
|
|
63
64
|
|
|
64
65
|
module.exports = function(eleventyConfig) {
|
|
66
|
+
bricksRegistry(eleventyConfig);
|
|
65
67
|
autoRaw(eleventyConfig);
|
|
66
68
|
|
|
67
69
|
// Your other configuration...
|
|
@@ -74,17 +76,122 @@ When using the plugin (Option 1), you can configure which helpers to enable:
|
|
|
74
76
|
|
|
75
77
|
| Option | Type | Default | Description |
|
|
76
78
|
|--------|------|---------|-------------|
|
|
79
|
+
| `bricksRegistry` | boolean | `false` | Enable the bricksRegistry system for dependency management |
|
|
77
80
|
| `autoRaw` | boolean | `false` | Enable the autoRaw preprocessor for Markdown files |
|
|
78
81
|
|
|
79
82
|
**Example:**
|
|
80
83
|
```javascript
|
|
81
84
|
eleventyConfig.addPlugin(eleventyBricks, {
|
|
85
|
+
bricksRegistry: true,
|
|
82
86
|
autoRaw: true
|
|
83
87
|
});
|
|
84
88
|
```
|
|
85
89
|
|
|
86
90
|
## Available 11ty Helpers
|
|
87
91
|
|
|
92
|
+
### bricksRegistry
|
|
93
|
+
|
|
94
|
+
A dependency management system for Eleventy that automatically collects and injects CSS and JavaScript dependencies (both external and inline) per page. This allows brick components to declare their dependencies, and the system will inject them in the correct location in your HTML.
|
|
95
|
+
|
|
96
|
+
**Why use this?**
|
|
97
|
+
|
|
98
|
+
When building reusable components (bricks) in Eleventy, you often need to include CSS and JavaScript dependencies. Instead of manually adding these to every page, `bricksRegistry` automatically:
|
|
99
|
+
- Collects dependencies from all bricks used on a page
|
|
100
|
+
- Categorizes them (external CSS, external JS, inline styles, inline scripts)
|
|
101
|
+
- Injects them in the correct location in your HTML output
|
|
102
|
+
|
|
103
|
+
**How it works:**
|
|
104
|
+
|
|
105
|
+
1. Use the `rootBrick` shortcode in your base template to mark where dependencies should be injected
|
|
106
|
+
2. Use the `brick` shortcode to register and render brick components that declare their dependencies
|
|
107
|
+
3. The system automatically collects all dependencies and injects them when the page is built
|
|
108
|
+
|
|
109
|
+
**Usage:**
|
|
110
|
+
|
|
111
|
+
1. Enable `bricksRegistry` in your Eleventy config:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
import { bricksRegistry } from "@anydigital/11ty-bricks";
|
|
115
|
+
|
|
116
|
+
export default function(eleventyConfig) {
|
|
117
|
+
bricksRegistry(eleventyConfig);
|
|
118
|
+
// Or use as plugin:
|
|
119
|
+
// eleventyConfig.addPlugin(eleventyBricks, { bricksRegistry: true });
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
2. Add the `rootBrick` shortcode in your base template (typically in the `<head>` section):
|
|
124
|
+
|
|
125
|
+
```njk
|
|
126
|
+
<head>
|
|
127
|
+
<meta charset="UTF-8">
|
|
128
|
+
<title>My Site</title>
|
|
129
|
+
{% rootBrick %}
|
|
130
|
+
<!-- Other head content -->
|
|
131
|
+
</head>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
3. Create brick components that declare their dependencies:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// myBrick.js
|
|
138
|
+
export default {
|
|
139
|
+
dependencies: [
|
|
140
|
+
'https://cdn.example.com/library.css',
|
|
141
|
+
'https://cdn.example.com/library.js'
|
|
142
|
+
],
|
|
143
|
+
style: `
|
|
144
|
+
.my-component { color: blue; }
|
|
145
|
+
`,
|
|
146
|
+
script: `
|
|
147
|
+
console.log('Component initialized');
|
|
148
|
+
`,
|
|
149
|
+
render: function() {
|
|
150
|
+
return '<div class="my-component">Hello World</div>';
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
4. Use the `brick` shortcode in your templates:
|
|
156
|
+
|
|
157
|
+
```njk
|
|
158
|
+
{% set myBrick = require('./myBrick.js') %}
|
|
159
|
+
{% brick myBrick %}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Brick Component Structure:**
|
|
163
|
+
|
|
164
|
+
A brick component is a JavaScript object with the following optional properties:
|
|
165
|
+
|
|
166
|
+
- `dependencies`: Array of URLs to external CSS or JavaScript files (e.g., `['https://cdn.example.com/style.css', 'https://cdn.example.com/script.js']`)
|
|
167
|
+
- `style`: String containing inline CSS
|
|
168
|
+
- `script`: String containing inline JavaScript
|
|
169
|
+
- `render`: Function that returns the HTML markup for the component
|
|
170
|
+
|
|
171
|
+
**Output:**
|
|
172
|
+
|
|
173
|
+
The system will automatically inject all dependencies in the order they were registered:
|
|
174
|
+
|
|
175
|
+
```html
|
|
176
|
+
<head>
|
|
177
|
+
<meta charset="UTF-8">
|
|
178
|
+
<title>My Site</title>
|
|
179
|
+
<link rel="stylesheet" href="https://cdn.example.com/library.css">
|
|
180
|
+
<style>.my-component { color: blue; }</style>
|
|
181
|
+
<script src="https://cdn.example.com/library.js"></script>
|
|
182
|
+
<script>console.log('Component initialized');</script>
|
|
183
|
+
<!-- Other head content -->
|
|
184
|
+
</head>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Features:**
|
|
188
|
+
|
|
189
|
+
- Automatic dependency collection per page
|
|
190
|
+
- Categorizes dependencies (CSS vs JS, external vs inline)
|
|
191
|
+
- Deduplicates dependencies (using Sets internally)
|
|
192
|
+
- Works with both external URLs and inline code
|
|
193
|
+
- Clears registry before each build to prevent stale data
|
|
194
|
+
|
|
88
195
|
### autoRaw
|
|
89
196
|
|
|
90
197
|
Prevents Nunjucks syntax from being processed in Markdown files by automatically wrapping `{{`, `}}`, `{%`, and `%}` with `{% raw %}` tags.
|
|
@@ -144,6 +251,43 @@ A reusable Nunjucks macro for rendering navigation menus with proper accessibili
|
|
|
144
251
|
</nav>
|
|
145
252
|
```
|
|
146
253
|
|
|
254
|
+
### Google Tag Manager Macro (`_gtm.njk`)
|
|
255
|
+
|
|
256
|
+
A reusable Nunjucks macro for integrating Google Tag Manager (GTM) into your site. Provides separate macros for the head and body GTM snippets.
|
|
257
|
+
|
|
258
|
+
**Usage:**
|
|
259
|
+
|
|
260
|
+
1. Import the macros in your base template:
|
|
261
|
+
|
|
262
|
+
```njk
|
|
263
|
+
{% import 'bricks/_gtm.njk' as gtm %}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
2. Call the macros in the appropriate locations:
|
|
267
|
+
|
|
268
|
+
```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>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Parameters:**
|
|
280
|
+
|
|
281
|
+
Both macros accept the same parameter:
|
|
282
|
+
- `gtmId`: Your Google Tag Manager container ID (e.g., `'GTM-XXXXXXX'`)
|
|
283
|
+
|
|
284
|
+
**Features:**
|
|
285
|
+
|
|
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
|
|
290
|
+
|
|
147
291
|
## CLI Helper Commands
|
|
148
292
|
|
|
149
293
|
After installing this package, the `download-files` command becomes available:
|
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
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 %}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export function bricksRegistry(eleventyConfig) {
|
|
2
|
+
|
|
3
|
+
// Brick Registry System
|
|
4
|
+
// Global registry to track dependencies per page
|
|
5
|
+
const brickRegistry = new Map();
|
|
6
|
+
|
|
7
|
+
// Helper to get or create page registry
|
|
8
|
+
function getPageRegistry(page) {
|
|
9
|
+
const pageUrl = page.url || page.outputPath || 'default';
|
|
10
|
+
if (!brickRegistry.has(pageUrl)) {
|
|
11
|
+
brickRegistry.set(pageUrl, {
|
|
12
|
+
dependencies: new Set(), // Raw dependencies (URLs) - categorized later
|
|
13
|
+
inlineStyles: new Set(),
|
|
14
|
+
inlineScripts: new Set()
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return brickRegistry.get(pageUrl);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Clear registry before each build
|
|
21
|
+
eleventyConfig.on("eleventy.before", async () => {
|
|
22
|
+
brickRegistry.clear();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// brick shortcode: registers and renders a brick component
|
|
26
|
+
eleventyConfig.addShortcode("brick", function(brickModule) {
|
|
27
|
+
const registry = getPageRegistry(this.page);
|
|
28
|
+
|
|
29
|
+
if (!brickModule) return '';
|
|
30
|
+
|
|
31
|
+
// Register external dependencies (categorized later in transform)
|
|
32
|
+
if (brickModule.dependencies) {
|
|
33
|
+
brickModule.dependencies.forEach(dep => {
|
|
34
|
+
registry.dependencies.add(dep);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Register inline styles directly from style variable
|
|
39
|
+
if (brickModule.style && brickModule.style.trim()) {
|
|
40
|
+
registry.inlineStyles.add(brickModule.style);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Register inline scripts directly from script variable
|
|
44
|
+
if (brickModule.script && brickModule.script.trim()) {
|
|
45
|
+
registry.inlineScripts.add(brickModule.script);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Render the brick using render() macro
|
|
49
|
+
if (brickModule.render && typeof brickModule.render === 'function') {
|
|
50
|
+
return brickModule.render();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return '';
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// rootBrick shortcode: outputs placeholder and base dependencies
|
|
57
|
+
eleventyConfig.addShortcode("rootBrick", function(options = {}) {
|
|
58
|
+
const registry = getPageRegistry(this.page);
|
|
59
|
+
|
|
60
|
+
// Register root dependencies if provided (categorized later in transform)
|
|
61
|
+
if (options.dependencies) {
|
|
62
|
+
options.dependencies.forEach(dep => {
|
|
63
|
+
registry.dependencies.add(dep);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Return placeholder comment that will be replaced by transform
|
|
68
|
+
return '<!-- BRICK_DEPENDENCIES_PLACEHOLDER -->';
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Transform to inject collected dependencies
|
|
72
|
+
eleventyConfig.addTransform("injectBrickDependencies", function(content, outputPath) {
|
|
73
|
+
if (!outputPath || !outputPath.endsWith(".html")) {
|
|
74
|
+
return content;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const pageUrl = this.page?.url || this.page?.outputPath || outputPath;
|
|
78
|
+
const registry = brickRegistry.get(pageUrl);
|
|
79
|
+
|
|
80
|
+
if (!registry || !content.includes('<!-- BRICK_DEPENDENCIES_PLACEHOLDER -->')) {
|
|
81
|
+
return content;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Categorize dependencies by type
|
|
85
|
+
const externalStyles = [];
|
|
86
|
+
const externalScripts = [];
|
|
87
|
+
|
|
88
|
+
registry.dependencies.forEach(dep => {
|
|
89
|
+
// Categorize by type
|
|
90
|
+
if (dep.endsWith('.css') || dep.includes('.css?')) {
|
|
91
|
+
externalStyles.push(dep);
|
|
92
|
+
} else if (dep.endsWith('.js') || dep.includes('.js?')) {
|
|
93
|
+
externalScripts.push(dep);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Build HTML for dependencies
|
|
98
|
+
let dependenciesHtml = '\n';
|
|
99
|
+
|
|
100
|
+
// Add external CSS links
|
|
101
|
+
externalStyles.forEach(href => {
|
|
102
|
+
dependenciesHtml += ` <link rel="stylesheet" href="${href}">\n`;
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Add inline styles
|
|
106
|
+
registry.inlineStyles.forEach(style => {
|
|
107
|
+
dependenciesHtml += ` <style>${style}</style>\n`;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Add external script links
|
|
111
|
+
externalScripts.forEach(src => {
|
|
112
|
+
dependenciesHtml += ` <script src="${src}"></script>\n`;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Add inline scripts
|
|
116
|
+
registry.inlineScripts.forEach(script => {
|
|
117
|
+
dependenciesHtml += ` <script>${script}</script>\n`;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
dependenciesHtml += ' ';
|
|
121
|
+
|
|
122
|
+
// Replace placeholder with actual dependencies
|
|
123
|
+
return content.replace('<!-- BRICK_DEPENDENCIES_PLACEHOLDER -->', dependenciesHtml);
|
|
124
|
+
});
|
|
125
|
+
}
|
package/src/index.cjs
CHANGED
|
@@ -10,8 +10,11 @@ module.exports = async function eleventyBricksPlugin(eleventyConfig, options) {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// Export individual helpers
|
|
13
|
+
module.exports.bricksRegistry = async function(eleventyConfig) {
|
|
14
|
+
const { bricksRegistry } = await import('./index.js');
|
|
15
|
+
return bricksRegistry(eleventyConfig);
|
|
16
|
+
};
|
|
13
17
|
module.exports.autoRaw = async function(eleventyConfig) {
|
|
14
18
|
const { autoRaw } = await import('./index.js');
|
|
15
19
|
return autoRaw(eleventyConfig);
|
|
16
20
|
};
|
|
17
|
-
|
package/src/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bricksRegistry } from "./bricksRegistry.js";
|
|
1
2
|
import { autoRaw } from "./autoRaw.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -8,17 +9,18 @@ import { autoRaw } from "./autoRaw.js";
|
|
|
8
9
|
*
|
|
9
10
|
* @param {Object} eleventyConfig - The Eleventy configuration object
|
|
10
11
|
* @param {Object} options - Plugin options
|
|
12
|
+
* @param {boolean} options.bricksRegistry - Enable bricksRegistry (default: false)
|
|
11
13
|
* @param {boolean} options.autoRaw - Enable autoRaw preprocessor (default: false)
|
|
12
14
|
*/
|
|
13
15
|
export default function eleventyBricksPlugin(eleventyConfig, options = {}) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (
|
|
16
|
+
if (options.bricksRegistry) {
|
|
17
|
+
bricksRegistry(eleventyConfig);
|
|
18
|
+
}
|
|
19
|
+
if (options.autoRaw) {
|
|
18
20
|
autoRaw(eleventyConfig);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
// Export individual helpers for granular usage
|
|
25
|
+
export { bricksRegistry };
|
|
23
26
|
export { autoRaw };
|
|
24
|
-
|