@anyblades/eleventy-blades 0.28.0-beta.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/.prettierrc.json +3 -0
- package/LICENSE +21 -0
- package/README.md +133 -0
- package/package.json +46 -0
- package/src/admin/index.html +12 -0
- package/src/do/README.md +53 -0
- package/src/do/package.json +15 -0
- package/src/eleventy.config.js +178 -0
- package/src/filters/attr_concat.js +107 -0
- package/src/filters/attr_concat.test.js +205 -0
- package/src/filters/attr_includes.js +65 -0
- package/src/filters/attr_includes.test.js +145 -0
- package/src/filters/attr_set.js +42 -0
- package/src/filters/attr_set.test.js +71 -0
- package/src/filters/fetch.js +118 -0
- package/src/filters/if.js +79 -0
- package/src/filters/if.test.js +63 -0
- package/src/filters/merge.js +78 -0
- package/src/filters/merge.test.js +51 -0
- package/src/filters/remove_tag.js +70 -0
- package/src/filters/remove_tag.test.js +60 -0
- package/src/filters/section.js +125 -0
- package/src/filters/section.test.js +174 -0
- package/src/filters/strip_tag.js +83 -0
- package/src/filters/strip_tag.test.js +74 -0
- package/src/filters/unindent.js +35 -0
- package/src/filters/unindent.test.js +49 -0
- package/src/index.js +122 -0
- package/src/processors/autoLinkFavicons.js +147 -0
- package/src/processors/autoLinkFavicons.test.js +452 -0
- package/src/processors/markdown.js +79 -0
- package/src/processors/markdown.test.js +207 -0
- package/src/siteData.js +25 -0
package/.prettierrc.json
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Anton Staroverov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
## <sub>Build Awesome /</sub><br> Eleventy blades <sup></sup>
|
|
2
|
+
|
|
3
|
+
<!--section:summary-->
|
|
4
|
+
|
|
5
|
+
Ultimate blade kit for 11ty (Build Awesome).
|
|
6
|
+
|
|
7
|
+
<!--section:docs-->
|
|
8
|
+
|
|
9
|
+
## Documentation
|
|
10
|
+
|
|
11
|
+
<!--prettier-ignore-->
|
|
12
|
+
- [Filters]( https://blades.ninja/build-awesome-11ty/filters/)
|
|
13
|
+
- [attr_concat]( https://blades.ninja/build-awesome-11ty/filters/#attr-concat),
|
|
14
|
+
[attr_includes]( https://blades.ninja/build-awesome-11ty/filters/#attr-includes),
|
|
15
|
+
[attr_set]( https://blades.ninja/build-awesome-11ty/filters/#attr-set)
|
|
16
|
+
- [date]( https://blades.ninja/build-awesome-11ty/filters/#date)
|
|
17
|
+
- [fetch]( https://blades.ninja/build-awesome-11ty/filters/#fetch) <!--{data-marker=🥷}-->
|
|
18
|
+
- [if]( https://blades.ninja/build-awesome-11ty/filters/#if)
|
|
19
|
+
- [markdownify]( https://blades.ninja/build-awesome-11ty/filters/#markdownify)
|
|
20
|
+
- [merge]( https://blades.ninja/build-awesome-11ty/filters/#merge)
|
|
21
|
+
- [remove_tag]( https://blades.ninja/build-awesome-11ty/filters/#remove-tag),
|
|
22
|
+
[strip_tag]( https://blades.ninja/build-awesome-11ty/filters/#strip-tag)
|
|
23
|
+
- [section]( https://blades.ninja/build-awesome-11ty/filters/#section) <!--{data-marker=🥷}-->
|
|
24
|
+
- [unindent]( https://blades.ninja/build-awesome-11ty/filters/#unindent)
|
|
25
|
+
- [Processors]( https://blades.ninja/build-awesome-11ty/processors/)
|
|
26
|
+
- [Auto link favicons]( https://blades.ninja/build-awesome-11ty/processors/#auto-link-favicons) <!--{data-marker=🥷}-->
|
|
27
|
+
- [Auto-raw tags]( https://blades.ninja/build-awesome-11ty/processors/#md-auto-raw)
|
|
28
|
+
- [Auto newlines-to-br](https://blades.ninja/build-awesome-11ty/processors/#md-auto-br)
|
|
29
|
+
- [Hidden markdown attrs<i> 🆕</i>](https://blades.ninja/build-awesome-11ty/processors/#md-hidden-attrs) <!--{data-marker=🥷}-->
|
|
30
|
+
- [Power tools]( https://blades.ninja/build-awesome-11ty/tools/)
|
|
31
|
+
- [Base config file]( https://blades.ninja/build-awesome-11ty/tools/#base-config) <!--{data-marker=🥷}-->
|
|
32
|
+
- [Base npm scripts]( https://blades.ninja/build-awesome-11ty/tools/#base-scripts) <!--{data-marker=🥷}-->
|
|
33
|
+
- [Data helpers]( https://blades.ninja/build-awesome-11ty/tools/#data-helpers)
|
|
34
|
+
- [Blades starters]( https://blades.ninja/build-awesome-11ty/tools/#starters) <!--{data-marker=🥷}-->
|
|
35
|
+
|
|
36
|
+
<!--{.unlist .columns}-->
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
<!--section:docs,install-->
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npm install @anyblades/eleventy-blades
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then choose one of the following options:
|
|
49
|
+
|
|
50
|
+
<mark>A. All-in</mark> managed by Eleventy Blades:
|
|
51
|
+
|
|
52
|
+
Consider symlinking entire `eleventy.config.js` as a set-and-forget zero-config zero-maintenance solution:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
ln -s ./node_modules/@anyblades/eleventy-blades/src/eleventy.config.js
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Learn more: https://blades.ninja/11ty/tools/#base-config
|
|
59
|
+
|
|
60
|
+
Living examples:
|
|
61
|
+
|
|
62
|
+
- https://github.com/anyblades/build-awesome-starter
|
|
63
|
+
- https://github.com/anyblades/bladeswitch
|
|
64
|
+
|
|
65
|
+
<mark>B. Base config</mark> by Eleventy Blades with your additions/overrides in `eleventy.config.js`:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import baseConfig from "@anyblades/eleventy-blades/base-config";
|
|
69
|
+
|
|
70
|
+
export default function (eleventyConfig) {
|
|
71
|
+
baseConfig(eleventyConfig);
|
|
72
|
+
|
|
73
|
+
// Your additions/overrides
|
|
74
|
+
...
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Living example: https://github.com/hostfurl/minformhf/blob/main/eleventy.config.js
|
|
79
|
+
|
|
80
|
+
<mark>C. Plug-in</mark> Eleventy Blades in your existing `eleventy.config.js`:
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import eleventyBladesPlugin from "@anyblades/eleventy-blades";
|
|
84
|
+
|
|
85
|
+
export default function (eleventyConfig) {
|
|
86
|
+
eleventyConfig.addPlugin(eleventyBladesPlugin, {
|
|
87
|
+
mdAutoRawTags: true,
|
|
88
|
+
mdAutoNl2br: true,
|
|
89
|
+
autoLinkFavicons: true,
|
|
90
|
+
siteData: true,
|
|
91
|
+
filters: ["attr_set", "attr_concat", ...],
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
<mark>D. Individual imports</mark> from Eleventy Blades in your `eleventy.config.js`:
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
import { siteData, mdAutoRawTags, mdAutoNl2br, autoLinkFavicons, attrSetFilter, attrConcatFilter, ... } from "@anyblades/eleventy-blades";
|
|
100
|
+
|
|
101
|
+
export default function (eleventyConfig) {
|
|
102
|
+
siteData(eleventyConfig);
|
|
103
|
+
mdAutoRawTags(eleventyConfig);
|
|
104
|
+
mdAutoNl2br(eleventyConfig);
|
|
105
|
+
autoLinkFavicons(eleventyConfig);
|
|
106
|
+
attrSetFilter(eleventyConfig);
|
|
107
|
+
attrConcatFilter(eleventyConfig);
|
|
108
|
+
...
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
<div><hr></div>
|
|
113
|
+
|
|
114
|
+
Or use a <mark>fully preconfigured template</mark> as an alternative option:
|
|
115
|
+
|
|
116
|
+
<nav>
|
|
117
|
+
|
|
118
|
+
[🥷 Build Awesome Starter ↗ <small style="white-space: nowrap">11ty + Tailwind + Typography + Blades</small>](https://github.com/anyblades/build-awesome-starter)<!--{role=button .outline}-->
|
|
119
|
+
|
|
120
|
+
[🥷 Bladeswitch Starter ↗ <small style="white-space: nowrap">11ty + Pico + Blades</small>](https://github.com/anyblades/bladeswitch)<!--{role=button .outline}-->
|
|
121
|
+
|
|
122
|
+
</nav>
|
|
123
|
+
|
|
124
|
+
<!--section:docs-->
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
Featured by:
|
|
129
|
+
|
|
130
|
+
- https://11tybundle.dev/blog/11ty-bundle-83/
|
|
131
|
+
- https://11tybundle.dev/categories/getting-started/
|
|
132
|
+
- https://hamatti.org/posts/markdown-content-split-to-sections-in-eleventy-and-nunjucks/#:~:text=anydigital
|
|
133
|
+
- https://github.com/anydigital/awesome-11ty-build-awesome
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anyblades/eleventy-blades",
|
|
3
|
+
"version": "0.28.0-beta.2",
|
|
4
|
+
"description": "A collection of helpful utilities and filters for Eleventy (11ty)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./src/index.js",
|
|
10
|
+
"require": "./src/index.cjs"
|
|
11
|
+
},
|
|
12
|
+
"./base-config": "./src/eleventy.config.js"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node --test src/**/*.test.js",
|
|
16
|
+
"prepublishOnly": "npm run test"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"11ty",
|
|
20
|
+
"eleventy",
|
|
21
|
+
"plugin",
|
|
22
|
+
"helpers",
|
|
23
|
+
"filters",
|
|
24
|
+
"markdown",
|
|
25
|
+
"nunjucks"
|
|
26
|
+
],
|
|
27
|
+
"author": "Anton Staroverov",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/anyblades/eleventy-blades.git"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/anyblades/eleventy-blades/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/anyblades/eleventy-blades#readme",
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@11ty/eleventy": "^3.0.0 || ^4.0.0-alpha.6"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@11ty/lodash-custom": "^4.17.21"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- https://sveltiacms.app/en/docs/start#manual-installation -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="robots" content="noindex" />
|
|
7
|
+
<title>Sveltia CMS</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/@sveltia/cms@0.128/dist/sveltia-cms.min.js"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
package/src/do/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
### Base 11ty npm scripts <small>via npm workspace</small> {#base-scripts}
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
**Installation:**
|
|
6
|
+
|
|
7
|
+
1. Install https://github.com/anyblades/eleventy-blades to reuse pre-defined 11ty scripts from there:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @anyblades/eleventy-blades
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Create a helper folder `do` to symlink the `do/package.json` within:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
mkdir do
|
|
17
|
+
cd ./do
|
|
18
|
+
ln -s ../node_modules/@anyblades/eleventy-blades/src/do/package.json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
3. Finally register `do` folder as npm workspace in your root `package.json`:
|
|
22
|
+
|
|
23
|
+
```json {data-caption=./package.json}
|
|
24
|
+
{
|
|
25
|
+
...
|
|
26
|
+
"workspaces": ["do"],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"start": "npm -w do run start",
|
|
29
|
+
"stage": "npm -w do run stage",
|
|
30
|
+
"build": "npm -w do run build"
|
|
31
|
+
},
|
|
32
|
+
...
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Done!** 🎉 Now you can run:
|
|
37
|
+
|
|
38
|
+
- `npm start` to start 11ty dev server with live reload and Tailwind watch mode
|
|
39
|
+
- `npm run stage` to build and serve production-like site locally
|
|
40
|
+
- `npm run build` to finally build the site for production
|
|
41
|
+
- all available scripts: https://github.com/anyblades/eleventy-blades/blob/main/src/do/package.json
|
|
42
|
+
|
|
43
|
+
Living examples:
|
|
44
|
+
|
|
45
|
+
- https://github.com/anyblades/build-awesome-starter
|
|
46
|
+
- https://github.com/anyblades/bladeswitch
|
|
47
|
+
|
|
48
|
+
**Benefits:**
|
|
49
|
+
|
|
50
|
+
- **Clean separation**: Keep build scripts separate from project configuration
|
|
51
|
+
- **Reusable workflows**: Update scripts by upgrading the package
|
|
52
|
+
- **Workspace isolation**: Scripts run in their own workspace context
|
|
53
|
+
- **Easy maintenance**: No need to manually maintain build scripts
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anyblades/eleventy-blades-do",
|
|
3
|
+
"private": true,
|
|
4
|
+
"scripts": {
|
|
5
|
+
"build": "npm run tw && npm run 11ty -- $ELTY_OPTIONS",
|
|
6
|
+
"start": "npm run 11ty -- $ELTY_OPTIONS --serve --incremental & npm run tw -- --watch",
|
|
7
|
+
"prerestart": "npm run 11ty:clean",
|
|
8
|
+
"stage": "npm run 11ty:clean; npm run build && serve ../_site",
|
|
9
|
+
"11ty": "cd ../ && NODE_OPTIONS='--preserve-symlinks' eleventy",
|
|
10
|
+
"11ty:clean": "rm -r ../_site",
|
|
11
|
+
"11ty:debug": "DEBUG=* npm run 11ty --",
|
|
12
|
+
"tw": "cd ../ && tailwindcss -i ./_styles/styles.css -o ./_public/styles.css",
|
|
13
|
+
"tw:debug": "DEBUG=* npm run tw --"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// <!--section:code-->```js
|
|
2
|
+
|
|
3
|
+
/* Plugins */
|
|
4
|
+
import { RenderPlugin } from "@11ty/eleventy";
|
|
5
|
+
import eleventyBladesPlugin from "@anyblades/eleventy-blades";
|
|
6
|
+
/* Dynamic plugins */
|
|
7
|
+
let eleventyNavigationPlugin;
|
|
8
|
+
try {
|
|
9
|
+
eleventyNavigationPlugin = (await import("@11ty/eleventy-navigation")).default;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
// @11ty/eleventy-navigation not installed
|
|
12
|
+
}
|
|
13
|
+
let pluginTOC;
|
|
14
|
+
try {
|
|
15
|
+
pluginTOC = (await import("@uncenter/eleventy-plugin-toc")).default;
|
|
16
|
+
} catch (e) {
|
|
17
|
+
// @uncenter/eleventy-plugin-toc not installed
|
|
18
|
+
}
|
|
19
|
+
let feedPlugin;
|
|
20
|
+
try {
|
|
21
|
+
feedPlugin = (await import("@11ty/eleventy-plugin-rss")).feedPlugin;
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// @11ty/eleventy-plugin-rss not installed
|
|
24
|
+
}
|
|
25
|
+
/* Libraries */
|
|
26
|
+
import markdownIt from "markdown-it";
|
|
27
|
+
/* Dynamic libraries */
|
|
28
|
+
let slugify;
|
|
29
|
+
try {
|
|
30
|
+
slugify = (await import("@sindresorhus/slugify")).default;
|
|
31
|
+
} catch (e) {
|
|
32
|
+
// @sindresorhus/slugify not installed
|
|
33
|
+
}
|
|
34
|
+
let markdownItAnchor;
|
|
35
|
+
try {
|
|
36
|
+
markdownItAnchor = (await import("markdown-it-anchor")).default;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// markdown-it-anchor not installed
|
|
39
|
+
}
|
|
40
|
+
let markdownItAttrs;
|
|
41
|
+
try {
|
|
42
|
+
markdownItAttrs = (await import("markdown-it-attrs")).default;
|
|
43
|
+
} catch (e) {
|
|
44
|
+
// markdown-it-attrs not installed
|
|
45
|
+
}
|
|
46
|
+
/* Data */
|
|
47
|
+
import yaml from "js-yaml";
|
|
48
|
+
import { readFileSync } from "node:fs";
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Eleventy Configuration
|
|
52
|
+
* @param {Object} eleventyConfig - The Eleventy configuration object
|
|
53
|
+
* @returns {Object} The Eleventy configuration object
|
|
54
|
+
*/
|
|
55
|
+
export default function (eleventyConfig) {
|
|
56
|
+
const inputDir = eleventyConfig.directories.input;
|
|
57
|
+
|
|
58
|
+
/* Jekyll parity */
|
|
59
|
+
eleventyConfig.addPassthroughCopy("assets");
|
|
60
|
+
eleventyConfig.addGlobalData("layout", "default");
|
|
61
|
+
eleventyConfig.setLiquidOptions({ dynamicPartials: false }); // allows unquoted Jekyll-style includes
|
|
62
|
+
eleventyConfig.addFilter("relative_url", (content) => content); // dummy
|
|
63
|
+
|
|
64
|
+
/* Plugins */
|
|
65
|
+
eleventyConfig.addPlugin(RenderPlugin);
|
|
66
|
+
if (eleventyNavigationPlugin) eleventyConfig.addPlugin(eleventyNavigationPlugin);
|
|
67
|
+
eleventyConfig.addPlugin(eleventyBladesPlugin, {
|
|
68
|
+
mdAutoNl2br: true,
|
|
69
|
+
mdAutoUncommentAttrs: true,
|
|
70
|
+
mdAutoRawTags: true,
|
|
71
|
+
autoLinkFavicons: true,
|
|
72
|
+
siteData: true,
|
|
73
|
+
filters: [
|
|
74
|
+
"attr_set",
|
|
75
|
+
"attr_includes",
|
|
76
|
+
"merge",
|
|
77
|
+
"remove_tag",
|
|
78
|
+
"if",
|
|
79
|
+
"attr_concat",
|
|
80
|
+
"fetch",
|
|
81
|
+
"section",
|
|
82
|
+
"strip_tag",
|
|
83
|
+
"unindent",
|
|
84
|
+
"date",
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
if (pluginTOC) {
|
|
88
|
+
eleventyConfig.addPlugin(pluginTOC, {
|
|
89
|
+
ignoredElements: ["sub", "[data-is-anchor]"],
|
|
90
|
+
ul: true,
|
|
91
|
+
wrapper: (toc) => `<div data-is-toc>${toc}</div>`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// https://www.11ty.dev/docs/plugins/rss/#virtual-template
|
|
95
|
+
if (feedPlugin) {
|
|
96
|
+
eleventyConfig.addCollection("feed", (collectionApi) => collectionApi.getAll().filter((item) => item.data.revised));
|
|
97
|
+
let siteData = {};
|
|
98
|
+
try {
|
|
99
|
+
siteData = yaml.load(readFileSync(`${inputDir}/_data/site.yml`, "utf8"));
|
|
100
|
+
} catch (e) {
|
|
101
|
+
// _data/site.yml not found
|
|
102
|
+
}
|
|
103
|
+
eleventyConfig.addPlugin(feedPlugin, {
|
|
104
|
+
type: "atom", // or "rss", "json"
|
|
105
|
+
outputPath: "/feed.xml",
|
|
106
|
+
collection: {
|
|
107
|
+
name: "feed", // iterate over `collections.posts`
|
|
108
|
+
limit: 100, // 0 means no limit
|
|
109
|
+
},
|
|
110
|
+
metadata: siteData,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Libraries */
|
|
115
|
+
let md = markdownIt({
|
|
116
|
+
html: true,
|
|
117
|
+
linkify: true,
|
|
118
|
+
});
|
|
119
|
+
if (markdownItAnchor) {
|
|
120
|
+
md = md.use(markdownItAnchor, {
|
|
121
|
+
slugify: slugify, // @TODO: TRICKS
|
|
122
|
+
permalink: markdownItAnchor.permalink.ariaHidden({
|
|
123
|
+
class: null,
|
|
124
|
+
renderAttrs: () => ({ "data-is-anchor": true }),
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (markdownItAttrs) md = md.use(markdownItAttrs);
|
|
129
|
+
eleventyConfig.setLibrary("md", md);
|
|
130
|
+
eleventyConfig.addFilter("markdownify", (content) => md.render(String(content ?? "")));
|
|
131
|
+
|
|
132
|
+
/* Data */
|
|
133
|
+
eleventyConfig.addDataExtension("yml", (contents) => yaml.load(contents));
|
|
134
|
+
|
|
135
|
+
/* Build */
|
|
136
|
+
eleventyConfig.addPassthroughCopy(
|
|
137
|
+
{
|
|
138
|
+
_public: ".",
|
|
139
|
+
...(inputDir !== "." && { [`${inputDir}/_public`]: "." }),
|
|
140
|
+
},
|
|
141
|
+
{ expand: true }, // This follows/resolves symbolic links
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
/* Dev tools */
|
|
145
|
+
// Follow symlinks in Chokidar used by 11ty to watch files
|
|
146
|
+
eleventyConfig.setChokidarConfig({ followSymlinks: true });
|
|
147
|
+
}
|
|
148
|
+
/*```
|
|
149
|
+
|
|
150
|
+
<!--section:docs-->
|
|
151
|
+
### Base `eleventy.config.js` {#base-config}
|
|
152
|
+
|
|
153
|
+
The package includes a fully-configured Eleventy config file `eleventy.config.js` that you can symlink to your project to get:
|
|
154
|
+
|
|
155
|
+
- All eleventy-blades plugins enabled
|
|
156
|
+
- Eleventy Navigation plugin
|
|
157
|
+
- Table of Contents plugin (conditionally loaded if installed)
|
|
158
|
+
- Markdown-it with anchors and attributes
|
|
159
|
+
- YAML data support
|
|
160
|
+
- CLI input directory support
|
|
161
|
+
- Symlink support for development
|
|
162
|
+
- _and more_
|
|
163
|
+
|
|
164
|
+
**Benefits of symlinking:**
|
|
165
|
+
|
|
166
|
+
- **Always up-to-date**: Configuration automatically updates when you upgrade the package
|
|
167
|
+
- **Less maintenance**: No need to manually sync configuration changes
|
|
168
|
+
- **Quick setup**: Get started immediately with best-practice configurations
|
|
169
|
+
- **Easy customization**: Override specific settings by creating your own config that imports from the symlinked version
|
|
170
|
+
|
|
171
|
+
**Installation as simple as:**
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
npm install @anyblades/eleventy-blades
|
|
175
|
+
ln -s ./node_modules/@anyblades/eleventy-blades/src/eleventy.config.js
|
|
176
|
+
```
|
|
177
|
+
<!--section-->
|
|
178
|
+
*/
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// <!--section:code-->```js
|
|
2
|
+
/**
|
|
3
|
+
* Concatenate values to an attribute array
|
|
4
|
+
*
|
|
5
|
+
* This function takes an object, an attribute name, and values to append.
|
|
6
|
+
* It returns a new object with the attribute as a combined array of unique items.
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} obj - The object to modify
|
|
9
|
+
* @param {string} attr - The attribute name
|
|
10
|
+
* @param {Array|string|*} values - Values to concatenate (array, JSON string array, or single value)
|
|
11
|
+
* @returns {Object} A new object with the combined unique array
|
|
12
|
+
*/
|
|
13
|
+
export function attrConcat(obj, attr, values) {
|
|
14
|
+
// Get the existing attribute value, default to empty array if not present
|
|
15
|
+
const existingArray = obj?.[attr] || [];
|
|
16
|
+
|
|
17
|
+
// Check if existing value is an array, convert if not
|
|
18
|
+
if (!Array.isArray(existingArray)) {
|
|
19
|
+
console.error(`attrConcat: Expected ${attr} to be an array, got ${typeof existingArray}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Process the values argument
|
|
23
|
+
let valuesToAdd = [];
|
|
24
|
+
if (Array.isArray(values)) {
|
|
25
|
+
valuesToAdd = values;
|
|
26
|
+
} else if (typeof values === "string" && values.length >= 2 && values.at(0) == "[" && values.at(-1) == "]") {
|
|
27
|
+
// Try to parse as JSON array
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(values);
|
|
30
|
+
if (Array.isArray(parsed)) {
|
|
31
|
+
valuesToAdd = parsed;
|
|
32
|
+
} else {
|
|
33
|
+
valuesToAdd = [values];
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// Not valid JSON, treat as single value
|
|
37
|
+
valuesToAdd = [values];
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
// If it's a single value, wrap it in an array
|
|
41
|
+
valuesToAdd = [values];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Combine arrays and remove duplicates using Set
|
|
45
|
+
const combinedArray = [...new Set([...existingArray, ...valuesToAdd])];
|
|
46
|
+
|
|
47
|
+
// Return a new object with the combined array
|
|
48
|
+
return {
|
|
49
|
+
...obj,
|
|
50
|
+
[attr]: combinedArray,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* attr_concat filter - Concatenate values to an attribute array
|
|
56
|
+
*
|
|
57
|
+
* This filter takes an object, an attribute name, and values to append.
|
|
58
|
+
* It returns a new object with the attribute as a combined array of unique items.
|
|
59
|
+
*
|
|
60
|
+
* @param {Object} eleventyConfig - The Eleventy configuration object
|
|
61
|
+
*/
|
|
62
|
+
export function attrConcatFilter(eleventyConfig) {
|
|
63
|
+
eleventyConfig.addFilter("attr_concat", attrConcat);
|
|
64
|
+
}
|
|
65
|
+
/*```
|
|
66
|
+
|
|
67
|
+
<!--section:docs-->
|
|
68
|
+
### `attr_concat`
|
|
69
|
+
|
|
70
|
+
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.
|
|
71
|
+
|
|
72
|
+
**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.
|
|
73
|
+
|
|
74
|
+
**Features:**
|
|
75
|
+
|
|
76
|
+
- Non-mutating: Creates a new object, leaving the original unchanged
|
|
77
|
+
- Automatically removes duplicates using Set
|
|
78
|
+
- Handles multiple input types: arrays, JSON string arrays (killer feature for `.liquid`), or single values
|
|
79
|
+
- Creates the attribute as an empty array if it doesn't exist
|
|
80
|
+
- Logs an error if the existing attribute is not an array
|
|
81
|
+
- `TBC:` Supports nested attributes (e.g., `data.tags`)
|
|
82
|
+
|
|
83
|
+
#### Example: Add tags to a post object in `.njk`:
|
|
84
|
+
|
|
85
|
+
```jinja2
|
|
86
|
+
{% set enhancedPost = post | attr_concat('tags', ['featured', 'popular']) %}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### `PRO` Example: Add scripts and styles to the `site` object in `.liquid`:
|
|
90
|
+
|
|
91
|
+
```liquid
|
|
92
|
+
{% capture _ %}[
|
|
93
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-tomorrow.min.css",
|
|
94
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/plugins/treeview/prism-treeview.min.css",
|
|
95
|
+
"https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7/css/all.min.css",
|
|
96
|
+
"/styles.css"
|
|
97
|
+
]{% endcapture %}
|
|
98
|
+
{% assign site = site | attr_concat: 'styles', _ %}
|
|
99
|
+
|
|
100
|
+
{% capture _ %}[
|
|
101
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js",
|
|
102
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js",
|
|
103
|
+
"https://cdn.jsdelivr.net/npm/prismjs@1/plugins/treeview/prism-treeview.min.js"
|
|
104
|
+
]{% endcapture %}
|
|
105
|
+
{% assign site = site | attr_concat: 'scripts', _ %}
|
|
106
|
+
```
|
|
107
|
+
<!--section--> */
|