Merge pull request #184 from 11ty/v9
Eleventy Base Blog v9 (using Eleventy v3 and ESM)
This commit is contained in:
commit
bff655c8a2
21
README.md
21
README.md
@ -1,4 +1,4 @@
|
|||||||
# eleventy-base-blog v8
|
# eleventy-base-blog v9
|
||||||
|
|
||||||
A starter repository showing how to build a blog with the [Eleventy](https://www.11ty.dev/) site generator (using the [v2.0 release](https://www.11ty.dev/blog/eleventy-v2/)).
|
A starter repository showing how to build a blog with the [Eleventy](https://www.11ty.dev/) site generator (using the [v2.0 release](https://www.11ty.dev/blog/eleventy-v2/)).
|
||||||
|
|
||||||
@ -45,36 +45,35 @@ Or you can run [debug mode](https://www.11ty.dev/docs/debugging/) to see all the
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Using [Eleventy v2.0](https://www.11ty.dev/blog/eleventy-v2/) with zero-JavaScript output.
|
- Using [Eleventy v3](https://github.com/11ty/eleventy/releases/tag/v3.0.0) with zero-JavaScript output.
|
||||||
- Content is exclusively pre-rendered (this is a static site).
|
- Content is exclusively pre-rendered (this is a static site).
|
||||||
- Can easily [deploy to a subfolder without changing any content](https://www.11ty.dev/docs/plugins/html-base/)
|
- Can easily [deploy to a subfolder without changing any content](https://www.11ty.dev/docs/plugins/html-base/)
|
||||||
- All URLs are decoupled from the content’s location on the file system.
|
- All URLs are decoupled from the content’s location on the file system.
|
||||||
- Configure templates via the [Eleventy Data Cascade](https://www.11ty.dev/docs/data-cascade/)
|
- Configure templates via the [Eleventy Data Cascade](https://www.11ty.dev/docs/data-cascade/)
|
||||||
- **Performance focused**: four-hundos Lighthouse score out of the box!
|
- **Performance focused**: four-hundos Lighthouse score out of the box!
|
||||||
- [View the Lighthouse report for the latest build](https://eleventy-base-blog.netlify.app/reports/lighthouse/) courtesy of the [Netlify Lighthouse plugin](https://github.com/netlify/netlify-plugin-lighthouse).
|
|
||||||
- _0 Cumulative Layout Shift_
|
- _0 Cumulative Layout Shift_
|
||||||
- _0ms Total Blocking Time_
|
- _0ms Total Blocking Time_
|
||||||
- Local development live reload provided by [Eleventy Dev Server](https://www.11ty.dev/docs/dev-server/).
|
- Local development live reload provided by [Eleventy Dev Server](https://www.11ty.dev/docs/dev-server/).
|
||||||
- Content-driven [navigation menu](https://www.11ty.dev/docs/plugins/navigation/)
|
- Content-driven [navigation menu](https://www.11ty.dev/docs/plugins/navigation/)
|
||||||
- [Image optimization](https://www.11ty.dev/docs/plugins/image/) via the `{% image %}` shortcode.
|
- Fully automated [Image optimization](https://www.11ty.dev/docs/plugins/image/)
|
||||||
- Zero-JavaScript output.
|
- Zero-JavaScript output.
|
||||||
- Support for modern image formats automatically (e.g. AVIF and WebP)
|
- Support for modern image formats automatically (e.g. AVIF and WebP)
|
||||||
|
- Processes images on-request during `--serve` for speedy local builds.
|
||||||
- Prefers `<img>` markup if possible (single image format) but switches automatically to `<picture>` for multiple image formats.
|
- Prefers `<img>` markup if possible (single image format) but switches automatically to `<picture>` for multiple image formats.
|
||||||
- Automated `<picture>` syntax markup with `srcset` and optional `sizes`
|
- Automated `<picture>` syntax markup with `srcset` and optional `sizes`
|
||||||
- Includes `width`/`height` attributes to avoid [content layout shift](https://web.dev/cls/).
|
- Includes `width`/`height` attributes to avoid [content layout shift](https://web.dev/cls/).
|
||||||
- Includes `loading="lazy"` for native lazy loading without JavaScript.
|
- Includes `loading="lazy"` for native lazy loading without JavaScript.
|
||||||
- Includes [`decoding="async"`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding)
|
- Includes [`decoding="async"`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding)
|
||||||
- Images can be co-located with blog post files.
|
- Images can be co-located with blog post files.
|
||||||
- View the [Image plugin source code](https://github.com/11ty/eleventy-base-blog/blob/main/eleventy.config.images.js)
|
|
||||||
- Per page CSS bundles [via `eleventy-plugin-bundle`](https://github.com/11ty/eleventy-plugin-bundle).
|
- Per page CSS bundles [via `eleventy-plugin-bundle`](https://github.com/11ty/eleventy-plugin-bundle).
|
||||||
- Built-in [syntax highlighter](https://www.11ty.dev/docs/plugins/syntaxhighlight/) (zero-JavaScript output).
|
- Built-in [syntax highlighter](https://www.11ty.dev/docs/plugins/syntaxhighlight/) (zero-JavaScript output).
|
||||||
|
- Draft content: use `draft: true` to mark any template as a draft. Drafts are **only** included during `--serve`/`--watch` and are excluded from full builds. This is driven by the `addPreprocessor` configuration API in `eleventy.config.js`. Schema validator will show an error if non-boolean value is set in data cascade.
|
||||||
- Blog Posts
|
- Blog Posts
|
||||||
- Draft posts: use `draft: true` to mark a blog post as a draft. Drafts are **only** included during `--serve`/`--watch` and are excluded from full builds. View the [Drafts plugin source code](https://github.com/11ty/eleventy-base-blog/blob/main/eleventy.config.drafts.js).
|
|
||||||
- Automated next/previous links
|
- Automated next/previous links
|
||||||
- Accessible deep links to headings
|
- Accessible deep links to headings
|
||||||
- Generated Pages
|
- Generated Pages
|
||||||
- Home, Archive, and About pages.
|
- Home, Archive, and About pages.
|
||||||
- [Feeds for Atom and JSON](https://www.11ty.dev/docs/plugins/rss/)
|
- [Atom feed included (with easy one-line swap to use RSS or JSON](https://www.11ty.dev/docs/plugins/rss/)
|
||||||
- `sitemap.xml`
|
- `sitemap.xml`
|
||||||
- Zero-maintenance tag pages ([View on the Demo](https://eleventy-base-blog.netlify.app/tags/))
|
- Zero-maintenance tag pages ([View on the Demo](https://eleventy-base-blog.netlify.app/tags/))
|
||||||
- Content not found (404) page
|
- Content not found (404) page
|
||||||
@ -83,20 +82,19 @@ Or you can run [debug mode](https://www.11ty.dev/docs/debugging/) to see all the
|
|||||||
|
|
||||||
- [Netlify](https://eleventy-base-blog.netlify.app/)
|
- [Netlify](https://eleventy-base-blog.netlify.app/)
|
||||||
- [Vercel](https://demo-base-blog.11ty.dev/)
|
- [Vercel](https://demo-base-blog.11ty.dev/)
|
||||||
- [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
|
|
||||||
- [Remix on Glitch](https://glitch.com/~11ty-eleventy-base-blog)
|
- [Remix on Glitch](https://glitch.com/~11ty-eleventy-base-blog)
|
||||||
- [Cloudflare Pages](https://eleventy-base-blog-d2a.pages.dev/)
|
- [Cloudflare Pages](https://eleventy-base-blog-d2a.pages.dev/)
|
||||||
|
- [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
|
||||||
|
|
||||||
## Deploy this to your own site
|
## Deploy this to your own site
|
||||||
|
|
||||||
Deploy this Eleventy site in just a few clicks on these services:
|
Deploy this Eleventy site in just a few clicks on these services:
|
||||||
|
|
||||||
|
- Read more about [Deploying an Eleventy project](https://www.11ty.dev/docs/deployment/) to the web.
|
||||||
- [Deploy this to **Netlify**](https://app.netlify.com/start/deploy?repository=https://github.com/11ty/eleventy-base-blog)
|
- [Deploy this to **Netlify**](https://app.netlify.com/start/deploy?repository=https://github.com/11ty/eleventy-base-blog)
|
||||||
- [Deploy this to **Vercel**](https://vercel.com/import/project?template=11ty%2Feleventy-base-blog)
|
- [Deploy this to **Vercel**](https://vercel.com/import/project?template=11ty%2Feleventy-base-blog)
|
||||||
- Look in `.github/workflows/gh-pages.yml.sample` for information on Deploying to **GitHub Pages**.
|
- Look in `.github/workflows/gh-pages.yml.sample` for information on Deploying to **GitHub Pages**.
|
||||||
- [Try it out on **Stackblitz**](https://stackblitz.com/github/11ty/eleventy-base-blog)
|
- [Try it out on **Stackblitz**](https://stackblitz.com/github/11ty/eleventy-base-blog)
|
||||||
- If you run Eleventy locally you can drag your `_site` folder to [`netlify.com/drop`](https://netlify.com/drop) to upload it without using `git`.
|
|
||||||
- Read more about [Deploying an Eleventy project](https://www.11ty.dev/docs/deployment/) to the web.
|
|
||||||
|
|
||||||
### Implementation Notes
|
### Implementation Notes
|
||||||
|
|
||||||
@ -105,9 +103,6 @@ Deploy this Eleventy site in just a few clicks on these services:
|
|||||||
- Use the `eleventyNavigation` key (via the [Eleventy Navigation plugin](https://www.11ty.dev/docs/plugins/navigation/)) in your front matter to add a template to the top level site navigation. This is in use on `content/index.njk` and `content/about/index.md`.
|
- Use the `eleventyNavigation` key (via the [Eleventy Navigation plugin](https://www.11ty.dev/docs/plugins/navigation/)) in your front matter to add a template to the top level site navigation. This is in use on `content/index.njk` and `content/about/index.md`.
|
||||||
- Content can be in _any template format_ (blog posts needn’t exclusively be markdown, for example). Configure your project’s supported templates in `eleventy.config.js` -> `templateFormats`.
|
- Content can be in _any template format_ (blog posts needn’t exclusively be markdown, for example). Configure your project’s supported templates in `eleventy.config.js` -> `templateFormats`.
|
||||||
- The `public` folder in your input directory will be copied to the output folder (via `addPassthroughCopy` in the `eleventy.config.js` file). This means `./public/css/*` will live at `./_site/css/*` after your build completes.
|
- The `public` folder in your input directory will be copied to the output folder (via `addPassthroughCopy` in the `eleventy.config.js` file). This means `./public/css/*` will live at `./_site/css/*` after your build completes.
|
||||||
- Provides two content feeds:
|
|
||||||
- `content/feed/feed.njk`
|
|
||||||
- `content/feed/json.njk`
|
|
||||||
- This project uses three [Eleventy Layouts](https://www.11ty.dev/docs/layouts/):
|
- This project uses three [Eleventy Layouts](https://www.11ty.dev/docs/layouts/):
|
||||||
- `_includes/layouts/base.njk`: the top level HTML structure
|
- `_includes/layouts/base.njk`: the top level HTML structure
|
||||||
- `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`)
|
- `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`)
|
||||||
|
40
_config/filters.js
Normal file
40
_config/filters.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
|
export default function(eleventyConfig) {
|
||||||
|
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
|
||||||
|
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
||||||
|
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
|
||||||
|
});
|
||||||
|
|
||||||
|
eleventyConfig.addFilter("htmlDateString", (dateObj) => {
|
||||||
|
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
||||||
|
return DateTime.fromJSDate(dateObj, { zone: "utc" }).toFormat('yyyy-LL-dd');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the first `n` elements of a collection.
|
||||||
|
eleventyConfig.addFilter("head", (array, n) => {
|
||||||
|
if(!Array.isArray(array) || array.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if( n < 0 ) {
|
||||||
|
return array.slice(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array.slice(0, n);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the smallest number argument
|
||||||
|
eleventyConfig.addFilter("min", (...numbers) => {
|
||||||
|
return Math.min.apply(null, numbers);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the keys used in an object
|
||||||
|
eleventyConfig.addFilter("getKeys", target => {
|
||||||
|
return Object.keys(target);
|
||||||
|
});
|
||||||
|
|
||||||
|
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
|
||||||
|
return (tags || []).filter(tag => ["all", "posts"].indexOf(tag) === -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
13
_data/eleventyDataSchema.js
Normal file
13
_data/eleventyDataSchema.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import { fromZodError } from 'zod-validation-error';
|
||||||
|
|
||||||
|
export default function(data) {
|
||||||
|
// Draft content, validate `draft` front matter
|
||||||
|
let result = z.object({
|
||||||
|
draft: z.boolean().or(z.undefined()),
|
||||||
|
}).safeParse(data);
|
||||||
|
|
||||||
|
if(result.error) {
|
||||||
|
throw fromZodError(result.error);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
export default {
|
||||||
title: "Eleventy Base Blog v8",
|
title: "Eleventy Base Blog v9",
|
||||||
url: "https://example.com/",
|
url: "https://example.com/",
|
||||||
language: "en",
|
language: "en",
|
||||||
description: "I am writing about my experiences as a naval navel-gazer.",
|
description: "I am writing about my experiences as a naval navel-gazer.",
|
||||||
|
@ -5,33 +5,36 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>{{ title or metadata.title }}</title>
|
<title>{{ title or metadata.title }}</title>
|
||||||
<meta name="description" content="{{ description or metadata.description }}">
|
<meta name="description" content="{{ description or metadata.description }}">
|
||||||
|
<link rel="alternate" href="feed/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
|
||||||
{#- Atom and JSON feeds included by default #}
|
|
||||||
<link rel="alternate" href="/feed/feed.xml" type="application/atom+xml" title="{{ metadata.title }}">
|
|
||||||
<link rel="alternate" href="/feed/feed.json" type="application/json" title="{{ metadata.title }}">
|
|
||||||
|
|
||||||
{#- Uncomment this if you’d like folks to know that you used Eleventy to build your site! #}
|
{#- Uncomment this if you’d like folks to know that you used Eleventy to build your site! #}
|
||||||
{#- <meta name="generator" content="{{ eleventy.generator }}"> #}
|
{#- <meta name="generator" content="{{ eleventy.generator }}"> #}
|
||||||
|
|
||||||
{#-
|
{#-
|
||||||
CSS bundles are provided via the `eleventy-plugin-bundle` plugin:
|
Plain-text bundles are provided via the `eleventy-plugin-bundle` plugin:
|
||||||
1. You can add to them using `{% css %}`
|
1. CSS:
|
||||||
2. You can get from them using `{% getBundle "css" %}` or `{% getBundleFileUrl "css" %}`
|
* Add to a per-page bundle using `{% css %}{% endcss %}`
|
||||||
3. You can do the same for JS: {% js %}{% endjs %} and <script>{% getBundle "js" %}</script>
|
* Retrieve bundle content using `{% getBundle "css" %}` or `{% getBundleFileUrl "css" %}`
|
||||||
4. Learn more: https://github.com/11ty/eleventy-plugin-bundle
|
2. Or for JavaScript:
|
||||||
|
* Add to a per-page bundle using `{% js %}{% endjs %}`
|
||||||
|
* Retrieve via `{% getBundle "js" %}` or `{% getBundleFileUrl "js" %}`
|
||||||
|
3. Learn more: https://github.com/11ty/eleventy-plugin-bundle
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{#- Add an arbitrary string to the bundle #}
|
{#- Add an arbitrary string to the bundle #}
|
||||||
{%- css %}* { box-sizing: border-box; }{% endcss %}
|
{%- css %}/* This is an arbitrary CSS string added to the bundle */{% endcss %}
|
||||||
{#- Add the contents of a file to the bundle #}
|
{#- Add the contents of a file to the bundle #}
|
||||||
{%- css %}{% include "public/css/index.css" %}{% endcss %}
|
{%- css %}{% include "public/css/index.css" %}{% endcss %}
|
||||||
{#- Or add from node_modules #}
|
{#- Or you can add from node_modules #}
|
||||||
{# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
|
{# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
|
||||||
|
|
||||||
{#- Render the CSS bundle using Inlined CSS (for the fastest site performance in production) #}
|
{#- Render the CSS bundle using inlined CSS (for the fastest site performance in production) #}
|
||||||
<style>{% getBundle "css" %}</style>
|
<style>{% getBundle "css" %}</style>
|
||||||
{#- Renders the CSS bundle using a separate file, if you can't set CSP directive style-src: 'unsafe-inline' #}
|
{#- Renders the CSS bundle using a separate file, if you can't set CSP directive style-src: 'unsafe-inline' #}
|
||||||
{#- <link rel="stylesheet" href="{% getBundleFileUrl "css" %}"> #}
|
{#- <link rel="stylesheet" href="{% getBundleFileUrl "css" %}"> #}
|
||||||
|
|
||||||
|
{#- Add the heading-anchors web component to the JavaScript bundle #}
|
||||||
|
{%- js %}{% include "node_modules/@zachleat/heading-anchors/heading-anchors.js" %}{% endjs %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a href="#skip" class="visually-hidden">Skip to main content</a>
|
<a href="#skip" class="visually-hidden">Skip to main content</a>
|
||||||
@ -51,11 +54,16 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="skip">
|
<main id="skip">
|
||||||
|
<heading-anchors>
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
|
</heading-anchors>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer></footer>
|
<footer>
|
||||||
|
<p><em>Built with <a href="https://www.11ty.dev/">{{ eleventy.generator }}</a></em></p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
<!-- This page `{{ page.url | htmlBaseUrl }}` was built on {% currentBuildDate %} -->
|
<!-- This page `{{ page.url | htmlBaseUrl }}` was built on {% currentBuildDate %} -->
|
||||||
|
<script type="module" src="{% getBundleFileUrl "js" %}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
layout: layouts/base.njk
|
layout: layouts/base.njk
|
||||||
---
|
---
|
||||||
<!-- Delete this message, it will also remove the component CSS from the bundle -->
|
<!-- Delete this block, which will also remove the component CSS from the bundle -->
|
||||||
{%- css %}{% include "public/css/message-box.css" %}{% endcss %}
|
{%- css %}{% include "public/css/message-box.css" %}{% endcss %}
|
||||||
<div class="message-box">
|
<div class="message-box">
|
||||||
<ol>
|
<ol>
|
||||||
<li>Edit the <code>_data/metadata.js</code> with your blog’s information.</li>
|
<li>Edit <code>_data/metadata.js</code> with your blog’s information.</li>
|
||||||
<li>(Optional) Edit <code>eleventy.config.js</code> with your <a href="https://www.11ty.dev/docs/config/">configuration preferences</a>.</li>
|
<li>(Optional) Edit <code>eleventy.config.js</code> with your <a href="https://www.11ty.dev/docs/config/">configuration preferences</a>.</li>
|
||||||
<li>Delete this message from <code>_includes/layouts/home.njk</code>.</li>
|
<li>Delete this message from <code>_includes/layouts/home.njk</code>.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
layout: layouts/base.njk
|
layout: layouts/base.njk
|
||||||
---
|
---
|
||||||
{# Only include the syntax highlighter CSS on blog posts #}
|
{# Only include the syntax highlighter CSS on blog posts, included with the CSS per-page bundle #}
|
||||||
{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
|
{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
|
||||||
{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
|
{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
@ -21,8 +21,8 @@ layout: layouts/base.njk
|
|||||||
{%- set nextPost = collections.posts | getNextCollectionItem %}
|
{%- set nextPost = collections.posts | getNextCollectionItem %}
|
||||||
{%- if nextPost or previousPost %}
|
{%- if nextPost or previousPost %}
|
||||||
<ul class="links-nextprev">
|
<ul class="links-nextprev">
|
||||||
{%- if previousPost %}<li>Previous: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></li>{% endif %}
|
{%- if previousPost %}<li class="links-nextprev-prev">← Previous<br> <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></li>{% endif %}
|
||||||
{%- if nextPost %}<li>Next: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></li>{% endif %}
|
{%- if nextPost %}<li class="links-nextprev-next">Next →<br><a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></li>{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
---
|
---
|
||||||
layout: layouts/home.njk
|
|
||||||
permalink: 404.html
|
permalink: 404.html
|
||||||
eleventyExcludeFromCollections: true
|
eleventyExcludeFromCollections: true
|
||||||
---
|
---
|
||||||
# Content not found.
|
# Content not found.
|
||||||
|
|
||||||
Go <a href="/">home</a>.
|
Go <a href="index.njk">home</a>.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
|
9
content/about.md
Normal file
9
content/about.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---js
|
||||||
|
const eleventyNavigation = {
|
||||||
|
key: "About",
|
||||||
|
order: 3
|
||||||
|
};
|
||||||
|
---
|
||||||
|
# About
|
||||||
|
|
||||||
|
I am a person that writes stuff.
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
layout: layouts/base.njk
|
|
||||||
eleventyNavigation:
|
|
||||||
key: About Me
|
|
||||||
order: 3
|
|
||||||
---
|
|
||||||
# About Me
|
|
||||||
|
|
||||||
I am a person that writes stuff.
|
|
@ -1,8 +1,8 @@
|
|||||||
---
|
---js
|
||||||
layout: layouts/home.njk
|
const eleventyNavigation = {
|
||||||
eleventyNavigation:
|
key: "Archive",
|
||||||
key: Archive
|
|
||||||
order: 2
|
order: 2
|
||||||
|
};
|
||||||
---
|
---
|
||||||
<h1>Archive</h1>
|
<h1>Archive</h1>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
export default {
|
||||||
tags: [
|
tags: [
|
||||||
"posts"
|
"posts"
|
||||||
],
|
],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---js
|
||||||
title: This is a fifth post (draft)
|
const title = "This is a fifth post (draft)";
|
||||||
date: 2023-01-23
|
const date = "2023-01-23";
|
||||||
draft: true
|
const draft = true;
|
||||||
---
|
---
|
||||||
This is a draft post
|
This is a draft post
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
title: This is my first post.
|
title: This is my first post.
|
||||||
description: This is a post on My Blog about agile frameworks.
|
description: This is a post on My Blog about agile frameworks.
|
||||||
date: 2018-05-01
|
date: 2018-05-01
|
||||||
tags:
|
tags: another tag
|
||||||
- another tag
|
|
||||||
---
|
---
|
||||||
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
|
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: This is my fourth post!
|
title: This is my fourth post
|
||||||
description: This is a post on My Blog about touchpoints and circling wagons.
|
description: This is a post on My Blog about touchpoints and circling wagons.
|
||||||
date: 2018-09-30
|
date: 2018-09-30
|
||||||
tags: second tag
|
tags: second tag
|
||||||
@ -8,7 +8,7 @@ Leverage agile frameworks to provide a robust synopsis for high level overviews.
|
|||||||
|
|
||||||
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
||||||
|
|
||||||
{% image "./possum.png", "A possum parent and two possum kids hanging from the iconic red balloon" %}
|
<img src="./possum.png" alt="A possum parent and two possum kids hanging from the iconic red balloon">
|
||||||
|
|
||||||
## Section Header
|
## Section Header
|
||||||
|
|
||||||
|
@ -2,15 +2,14 @@
|
|||||||
title: This is my second post with a much longer title.
|
title: This is my second post with a much longer title.
|
||||||
description: This is a post on My Blog about leveraging agile frameworks.
|
description: This is a post on My Blog about leveraging agile frameworks.
|
||||||
date: 2018-07-04
|
date: 2018-07-04
|
||||||
tags:
|
tags: number 2
|
||||||
- number 2
|
|
||||||
---
|
---
|
||||||
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
|
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
|
||||||
|
|
||||||
## Section Header
|
## Section Header
|
||||||
|
|
||||||
<a href="/blog/firstpost/">First post</a>
|
<a href="/blog/firstpost.md">First post</a>
|
||||||
<a href="/blog/thirdpost/">Third post</a>
|
<a href="blog/thirdpost.md">Third post</a>
|
||||||
|
|
||||||
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
||||||
|
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
title: This is my third post.
|
title: This is my third post.
|
||||||
description: This is a post on My Blog about win-win survival strategies.
|
description: This is a post on My Blog about win-win survival strategies.
|
||||||
date: 2018-08-24
|
date: 2018-08-24
|
||||||
tags:
|
tags: ["second tag", "posts with two tags"]
|
||||||
- second tag
|
|
||||||
- posts with two tags
|
|
||||||
---
|
---
|
||||||
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
|
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
|
||||||
|
|
||||||
## Code
|
## Code
|
||||||
|
|
||||||
### Styled (with Syntax)
|
### This is a very long heading that I want to wrap This is a very long heading that I want to wrap This is a very long heading that I want to wrap This is a very long heading that I want to wrap
|
||||||
|
|
||||||
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
||||||
|
|
||||||
@ -25,7 +23,7 @@ function myCommand() {
|
|||||||
console.log('Test');
|
console.log('Test');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Unstyled
|
### Heading with a [link](#code)
|
||||||
|
|
||||||
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
|
||||||
|
|
||||||
|
3
content/content.11tydata.js
Normal file
3
content/content.11tydata.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
layout: "layouts/home.njk",
|
||||||
|
};
|
1
content/feed/.virtual
Normal file
1
content/feed/.virtual
Normal file
@ -0,0 +1 @@
|
|||||||
|
For RSS feed, Atom Feed, and JSON feed templates, see the plugin in eleventy.config.js
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
eleventyExcludeFromCollections: true
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
# Metadata comes from _data/metadata.js
|
|
||||||
permalink: /feed/feed.xml
|
|
||||||
---
|
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="{{ metadata.language }}">
|
|
||||||
<title>{{ metadata.title }}</title>
|
|
||||||
<subtitle>{{ metadata.description }}</subtitle>
|
|
||||||
<link href="{{ permalink | htmlBaseUrl(metadata.url) }}" rel="self"/>
|
|
||||||
<link href="{{ metadata.url | addPathPrefixToFullUrl }}"/>
|
|
||||||
<updated>{{ collections.posts | getNewestCollectionItemDate | dateToRfc3339 }}</updated>
|
|
||||||
<id>{{ metadata.url }}</id>
|
|
||||||
<author>
|
|
||||||
<name>{{ metadata.author.name }}</name>
|
|
||||||
<email>{{ metadata.author.email }}</email>
|
|
||||||
</author>
|
|
||||||
{%- for post in collections.posts | reverse %}
|
|
||||||
{% set absolutePostUrl %}{{ post.url | htmlBaseUrl(metadata.url) }}{% endset %}
|
|
||||||
<entry>
|
|
||||||
<title>{{ post.data.title }}</title>
|
|
||||||
<link href="{{ absolutePostUrl }}"/>
|
|
||||||
<updated>{{ post.date | dateToRfc3339 }}</updated>
|
|
||||||
<id>{{ absolutePostUrl }}</id>
|
|
||||||
<content type="html">{{ post.templateContent | transformWithHtmlBase(absolutePostUrl, post.url) }}</content>
|
|
||||||
</entry>
|
|
||||||
{%- endfor %}
|
|
||||||
</feed>
|
|
@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
# Metadata comes from _data/metadata.js
|
|
||||||
permalink: /feed/feed.json
|
|
||||||
---
|
|
||||||
{
|
|
||||||
"version": "https://jsonfeed.org/version/1.1",
|
|
||||||
"title": "{{ metadata.title }}",
|
|
||||||
"language": "{{ metadata.language }}",
|
|
||||||
"home_page_url": "{{ metadata.url | addPathPrefixToFullUrl }}",
|
|
||||||
"feed_url": "{{ permalink | htmlBaseUrl(metadata.url) }}",
|
|
||||||
"description": "{{ metadata.description }}",
|
|
||||||
"author": {
|
|
||||||
"name": "{{ metadata.author.name }}",
|
|
||||||
"url": "{{ metadata.author.url }}"
|
|
||||||
},
|
|
||||||
"items": [
|
|
||||||
{%- for post in collections.posts | reverse %}
|
|
||||||
{%- set absolutePostUrl = post.url | htmlBaseUrl(metadata.url) %}
|
|
||||||
{
|
|
||||||
"id": "{{ absolutePostUrl }}",
|
|
||||||
"url": "{{ absolutePostUrl }}",
|
|
||||||
"title": "{{ post.data.title }}",
|
|
||||||
"content_html": {% if post.templateContent %}{{ post.templateContent | transformWithHtmlBase(absolutePostUrl, post.url) | dump | safe }}{% else %}""{% endif %},
|
|
||||||
"date_published": "{{ post.date | dateToRfc3339 }}"
|
|
||||||
}
|
|
||||||
{% if not loop.last %},{% endif %}
|
|
||||||
{%- endfor %}
|
|
||||||
]
|
|
||||||
}
|
|
89
content/feed/pretty-atom-feed.xsl
Normal file
89
content/feed/pretty-atom-feed.xsl
Normal file
File diff suppressed because one or more lines are too long
@ -1,9 +1,10 @@
|
|||||||
---
|
---js
|
||||||
layout: layouts/home.njk
|
const eleventyNavigation = {
|
||||||
eleventyNavigation:
|
key: "Home",
|
||||||
key: Home
|
|
||||||
order: 1
|
order: 1
|
||||||
numberOfLatestPostsToShow: 3
|
};
|
||||||
|
|
||||||
|
const numberOfLatestPostsToShow = 3;
|
||||||
---
|
---
|
||||||
{% set postsCount = collections.posts | length %}
|
{% set postsCount = collections.posts | length %}
|
||||||
{% set latestPostsCount = postsCount | min(numberOfLatestPostsToShow) %}
|
{% set latestPostsCount = postsCount | min(numberOfLatestPostsToShow) %}
|
||||||
@ -15,7 +16,7 @@ numberOfLatestPostsToShow: 3
|
|||||||
|
|
||||||
{% set morePosts = postsCount - numberOfLatestPostsToShow %}
|
{% set morePosts = postsCount - numberOfLatestPostsToShow %}
|
||||||
{% if morePosts > 0 %}
|
{% if morePosts > 0 %}
|
||||||
<p>{{ morePosts }} more post{% if morePosts != 1 %}s{% endif %} can be found in <a href="/blog/">the archive</a>.</p>
|
<p>{{ morePosts }} more post{% if morePosts != 1 %}s{% endif %} can be found in <a href="blog.njk">the archive</a>.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# List every content page in the project #}
|
{# List every content page in the project #}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
permalink: /sitemap.xml
|
permalink: /sitemap.xml
|
||||||
|
layout: false
|
||||||
eleventyExcludeFromCollections: true
|
eleventyExcludeFromCollections: true
|
||||||
---
|
---
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
25
content/tag-pages.njk
Normal file
25
content/tag-pages.njk
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
---js
|
||||||
|
// <script>
|
||||||
|
const pagination = {
|
||||||
|
data: "collections",
|
||||||
|
size: 1,
|
||||||
|
alias: "tag",
|
||||||
|
filter: ["all", "posts"],
|
||||||
|
// addAllPagesToCollections: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const eleventyExcludeFromCollections = true;
|
||||||
|
|
||||||
|
const eleventyComputed = {
|
||||||
|
title: "Tagged '{{ tag }}'",
|
||||||
|
permalink: function(data) {
|
||||||
|
return `/tags/${this.slugify(data.tag)}/`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
---
|
||||||
|
<h1>Tagged “{{ tag }}”</h1>
|
||||||
|
|
||||||
|
{% set postslist = collections[ tag ] %}
|
||||||
|
{% include "postslist.njk" %}
|
||||||
|
|
||||||
|
<p>See <a href="tags.njk">all tags</a>.</p>
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
permalink: /tags/
|
|
||||||
layout: layouts/home.njk
|
|
||||||
---
|
|
||||||
<h1>Tags</h1>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{% for tag in collections.all | getAllTags | filterTagList %}
|
|
||||||
{% set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
|
|
||||||
<li><a href="{{ tagUrl }}" class="post-tag">{{ tag }}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
@ -1,22 +1,8 @@
|
|||||||
---
|
<h1>Tags</h1>
|
||||||
pagination:
|
|
||||||
data: collections
|
|
||||||
size: 1
|
|
||||||
alias: tag
|
|
||||||
filter:
|
|
||||||
- all
|
|
||||||
- post
|
|
||||||
- posts
|
|
||||||
- tagList
|
|
||||||
addAllPagesToCollections: true
|
|
||||||
layout: layouts/home.njk
|
|
||||||
eleventyComputed:
|
|
||||||
title: Tagged “{{ tag }}”
|
|
||||||
permalink: /tags/{{ tag | slugify }}/
|
|
||||||
---
|
|
||||||
<h1>Tagged “{{ tag }}”</h1>
|
|
||||||
|
|
||||||
{% set postslist = collections[ tag ] %}
|
<ul>
|
||||||
{% include "postslist.njk" %}
|
{% for tag in collections | getKeys | filterTagList %}
|
||||||
|
{% set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
|
||||||
<p>See <a href="/tags/">all tags</a>.</p>
|
<li><a href="{{ tagUrl }}" class="post-tag">{{ tag }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
function eleventyComputedPermalink() {
|
|
||||||
// When using `addGlobalData` and you *want* to return a function, you must nest functions like this.
|
|
||||||
// `addGlobalData` acts like a global data file and runs the top level function it receives.
|
|
||||||
return (data) => {
|
|
||||||
// Always skip during non-watch/serve builds
|
|
||||||
if(data.draft && !process.env.BUILD_DRAFTS) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.permalink;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function eleventyComputedExcludeFromCollections() {
|
|
||||||
// When using `addGlobalData` and you *want* to return a function, you must nest functions like this.
|
|
||||||
// `addGlobalData` acts like a global data file and runs the top level function it receives.
|
|
||||||
return (data) => {
|
|
||||||
// Always exclude from non-watch/serve builds
|
|
||||||
if(data.draft && !process.env.BUILD_DRAFTS) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.eleventyExcludeFromCollections;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.eleventyComputedPermalink = eleventyComputedPermalink;
|
|
||||||
module.exports.eleventyComputedExcludeFromCollections = eleventyComputedExcludeFromCollections;
|
|
||||||
|
|
||||||
module.exports = eleventyConfig => {
|
|
||||||
eleventyConfig.addGlobalData("eleventyComputed.permalink", eleventyComputedPermalink);
|
|
||||||
eleventyConfig.addGlobalData("eleventyComputed.eleventyExcludeFromCollections", eleventyComputedExcludeFromCollections);
|
|
||||||
|
|
||||||
let logged = false;
|
|
||||||
eleventyConfig.on("eleventy.before", ({runMode}) => {
|
|
||||||
let text = "Excluding";
|
|
||||||
// Only show drafts in serve/watch modes
|
|
||||||
if(runMode === "serve" || runMode === "watch") {
|
|
||||||
process.env.BUILD_DRAFTS = true;
|
|
||||||
text = "Including";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only log once.
|
|
||||||
if(!logged) {
|
|
||||||
console.log( `[11ty/eleventy-base-blog] ${text} drafts.` );
|
|
||||||
}
|
|
||||||
|
|
||||||
logged = true;
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
const eleventyImage = require("@11ty/eleventy-img");
|
|
||||||
|
|
||||||
function relativeToInputPath(inputPath, relativeFilePath) {
|
|
||||||
let split = inputPath.split("/");
|
|
||||||
split.pop();
|
|
||||||
|
|
||||||
return path.resolve(split.join(path.sep), relativeFilePath);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFullUrl(url) {
|
|
||||||
try {
|
|
||||||
new URL(url);
|
|
||||||
return true;
|
|
||||||
} catch(e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(eleventyConfig) {
|
|
||||||
// Eleventy Image shortcode
|
|
||||||
// https://www.11ty.dev/docs/plugins/image/
|
|
||||||
eleventyConfig.addAsyncShortcode("image", async function imageShortcode(src, alt, widths, sizes) {
|
|
||||||
// Full list of formats here: https://www.11ty.dev/docs/plugins/image/#output-formats
|
|
||||||
// Warning: Avif can be resource-intensive so take care!
|
|
||||||
let formats = ["avif", "webp", "auto"];
|
|
||||||
let input;
|
|
||||||
if(isFullUrl(src)) {
|
|
||||||
input = src;
|
|
||||||
} else {
|
|
||||||
input = relativeToInputPath(this.page.inputPath, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
let metadata = await eleventyImage(input, {
|
|
||||||
widths: widths || ["auto"],
|
|
||||||
formats,
|
|
||||||
outputDir: path.join(eleventyConfig.dir.output, "img"), // Advanced usage note: `eleventyConfig.dir` works here because we’re using addPlugin.
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO loading=eager and fetchpriority=high
|
|
||||||
let imageAttributes = {
|
|
||||||
alt,
|
|
||||||
sizes,
|
|
||||||
loading: "lazy",
|
|
||||||
decoding: "async",
|
|
||||||
};
|
|
||||||
|
|
||||||
return eleventyImage.generateHTML(metadata, imageAttributes);
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,23 +1,27 @@
|
|||||||
const { DateTime } = require("luxon");
|
import { IdAttributePlugin, InputPathToUrlTransformPlugin, HtmlBasePlugin } from "@11ty/eleventy";
|
||||||
const markdownItAnchor = require("markdown-it-anchor");
|
import { feedPlugin } from "@11ty/eleventy-plugin-rss";
|
||||||
|
import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
|
||||||
|
import pluginNavigation from "@11ty/eleventy-navigation";
|
||||||
|
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
|
||||||
|
|
||||||
const pluginRss = require("@11ty/eleventy-plugin-rss");
|
import pluginFilters from "./_config/filters.js";
|
||||||
const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
|
|
||||||
const pluginBundle = require("@11ty/eleventy-plugin-bundle");
|
|
||||||
const pluginNavigation = require("@11ty/eleventy-navigation");
|
|
||||||
const { EleventyHtmlBasePlugin } = require("@11ty/eleventy");
|
|
||||||
|
|
||||||
const pluginDrafts = require("./eleventy.config.drafts.js");
|
/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
|
||||||
const pluginImages = require("./eleventy.config.images.js");
|
export default async function(eleventyConfig) {
|
||||||
|
// Drafts, see also _data/eleventyDataSchema.js
|
||||||
|
eleventyConfig.addPreprocessor("drafts", "*", (data, content) => {
|
||||||
|
if(data.draft && process.env.ELEVENTY_RUN_MODE === "build") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/** @param {import('@11ty/eleventy').UserConfig} eleventyConfig */
|
|
||||||
module.exports = function(eleventyConfig) {
|
|
||||||
// Copy the contents of the `public` folder to the output folder
|
// Copy the contents of the `public` folder to the output folder
|
||||||
// For example, `./public/css/` ends up in `_site/css/`
|
// For example, `./public/css/` ends up in `_site/css/`
|
||||||
eleventyConfig.addPassthroughCopy({
|
eleventyConfig
|
||||||
"./public/": "/",
|
.addPassthroughCopy({
|
||||||
"./node_modules/prismjs/themes/prism-okaidia.css": "/css/prism-okaidia.css"
|
"./public/": "/"
|
||||||
});
|
})
|
||||||
|
.addPassthroughCopy("./content/feed/pretty-atom-feed.xsl");
|
||||||
|
|
||||||
// Run Eleventy when these files change:
|
// Run Eleventy when these files change:
|
||||||
// https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets
|
// https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets
|
||||||
@ -25,77 +29,78 @@ module.exports = function(eleventyConfig) {
|
|||||||
// Watch content images for the image pipeline.
|
// Watch content images for the image pipeline.
|
||||||
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
|
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
|
||||||
|
|
||||||
// App plugins
|
// Per-page bundles, see https://github.com/11ty/eleventy-plugin-bundle
|
||||||
eleventyConfig.addPlugin(pluginDrafts);
|
// Adds the {% css %} paired shortcode
|
||||||
eleventyConfig.addPlugin(pluginImages);
|
eleventyConfig.addBundle("css", {
|
||||||
|
toFileDirectory: "dist",
|
||||||
|
});
|
||||||
|
// Adds the {% js %} paired shortcode
|
||||||
|
eleventyConfig.addBundle("js", {
|
||||||
|
toFileDirectory: "dist",
|
||||||
|
});
|
||||||
|
|
||||||
// Official plugins
|
// Official plugins
|
||||||
eleventyConfig.addPlugin(pluginRss);
|
|
||||||
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
|
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
|
||||||
preAttributes: { tabindex: 0 }
|
preAttributes: { tabindex: 0 }
|
||||||
});
|
});
|
||||||
eleventyConfig.addPlugin(pluginNavigation);
|
eleventyConfig.addPlugin(pluginNavigation);
|
||||||
eleventyConfig.addPlugin(EleventyHtmlBasePlugin);
|
eleventyConfig.addPlugin(HtmlBasePlugin);
|
||||||
eleventyConfig.addPlugin(pluginBundle);
|
eleventyConfig.addPlugin(InputPathToUrlTransformPlugin);
|
||||||
|
|
||||||
|
eleventyConfig.addPlugin(feedPlugin, {
|
||||||
|
type: "atom", // or "rss", "json"
|
||||||
|
outputPath: "/feed/feed.xml",
|
||||||
|
stylesheet: "pretty-atom-feed.xsl",
|
||||||
|
templateData: {
|
||||||
|
eleventyNavigation: {
|
||||||
|
key: "Feed",
|
||||||
|
order: 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
collection: {
|
||||||
|
name: "posts",
|
||||||
|
limit: 10,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
language: "en",
|
||||||
|
title: "Blog Title",
|
||||||
|
subtitle: "This is a longer description about your blog.",
|
||||||
|
base: "https://example.com/",
|
||||||
|
author: {
|
||||||
|
name: "Your Name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Image optimization: https://www.11ty.dev/docs/plugins/image/#eleventy-transform
|
||||||
|
eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
|
||||||
|
// File extensions to process in _site folder
|
||||||
|
extensions: "html",
|
||||||
|
|
||||||
|
// Output formats for each image.
|
||||||
|
formats: ["avif", "webp", "auto"],
|
||||||
|
|
||||||
|
// widths: ["auto"],
|
||||||
|
|
||||||
|
defaultAttributes: {
|
||||||
|
// e.g. <img loading decoding> assigned on the HTML tag will override these values.
|
||||||
|
loading: "lazy",
|
||||||
|
decoding: "async",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
|
eleventyConfig.addPlugin(pluginFilters);
|
||||||
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
|
|
||||||
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
|
|
||||||
});
|
|
||||||
|
|
||||||
eleventyConfig.addFilter('htmlDateString', (dateObj) => {
|
eleventyConfig.addPlugin(IdAttributePlugin, {
|
||||||
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
|
// by default we use Eleventy’s built-in `slugify` filter:
|
||||||
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd');
|
// slugify: eleventyConfig.getFilter("slugify"),
|
||||||
});
|
// selector: "h1,h2,h3,h4,h5,h6", // default
|
||||||
|
|
||||||
// Get the first `n` elements of a collection.
|
|
||||||
eleventyConfig.addFilter("head", (array, n) => {
|
|
||||||
if(!Array.isArray(array) || array.length === 0) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
if( n < 0 ) {
|
|
||||||
return array.slice(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.slice(0, n);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the smallest number argument
|
|
||||||
eleventyConfig.addFilter("min", (...numbers) => {
|
|
||||||
return Math.min.apply(null, numbers);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return all the tags used in a collection
|
|
||||||
eleventyConfig.addFilter("getAllTags", collection => {
|
|
||||||
let tagSet = new Set();
|
|
||||||
for(let item of collection) {
|
|
||||||
(item.data.tags || []).forEach(tag => tagSet.add(tag));
|
|
||||||
}
|
|
||||||
return Array.from(tagSet);
|
|
||||||
});
|
|
||||||
|
|
||||||
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
|
|
||||||
return (tags || []).filter(tag => ["all", "nav", "post", "posts"].indexOf(tag) === -1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Customize Markdown library settings:
|
|
||||||
eleventyConfig.amendLibrary("md", mdLib => {
|
|
||||||
mdLib.use(markdownItAnchor, {
|
|
||||||
permalink: markdownItAnchor.permalink.ariaHidden({
|
|
||||||
placement: "after",
|
|
||||||
class: "header-anchor",
|
|
||||||
symbol: "#",
|
|
||||||
ariaHidden: false,
|
|
||||||
}),
|
|
||||||
level: [1,2,3,4],
|
|
||||||
slugify: eleventyConfig.getFilter("slugify")
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
eleventyConfig.addShortcode("currentBuildDate", () => {
|
eleventyConfig.addShortcode("currentBuildDate", () => {
|
||||||
return (new Date()).toISOString();
|
return (new Date()).toISOString();
|
||||||
})
|
});
|
||||||
|
|
||||||
// Features to make your build faster (when you need them)
|
// Features to make your build faster (when you need them)
|
||||||
|
|
||||||
@ -104,8 +109,9 @@ module.exports = function(eleventyConfig) {
|
|||||||
// https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve
|
// https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve
|
||||||
|
|
||||||
// eleventyConfig.setServerPassthroughCopyBehavior("passthrough");
|
// eleventyConfig.setServerPassthroughCopyBehavior("passthrough");
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
export const config = {
|
||||||
// Control which files Eleventy will process
|
// Control which files Eleventy will process
|
||||||
// e.g.: *.md, *.njk, *.html, *.liquid
|
// e.g.: *.md, *.njk, *.html, *.liquid
|
||||||
templateFormats: [
|
templateFormats: [
|
||||||
@ -113,6 +119,7 @@ module.exports = function(eleventyConfig) {
|
|||||||
"njk",
|
"njk",
|
||||||
"html",
|
"html",
|
||||||
"liquid",
|
"liquid",
|
||||||
|
"11ty.js",
|
||||||
],
|
],
|
||||||
|
|
||||||
// Pre-process *.md files with: (default: `liquid`)
|
// Pre-process *.md files with: (default: `liquid`)
|
||||||
@ -124,8 +131,8 @@ module.exports = function(eleventyConfig) {
|
|||||||
// These are all optional:
|
// These are all optional:
|
||||||
dir: {
|
dir: {
|
||||||
input: "content", // default: "."
|
input: "content", // default: "."
|
||||||
includes: "../_includes", // default: "_includes"
|
includes: "../_includes", // default: "_includes" (`input` relative)
|
||||||
data: "../_data", // default: "_data"
|
data: "../_data", // default: "_data" (`input` relative)
|
||||||
output: "_site"
|
output: "_site"
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -139,6 +146,6 @@ module.exports = function(eleventyConfig) {
|
|||||||
// When paired with the HTML <base> plugin https://www.11ty.dev/docs/plugins/html-base/
|
// When paired with the HTML <base> plugin https://www.11ty.dev/docs/plugins/html-base/
|
||||||
// it will transform any absolute URLs in your HTML to include this
|
// it will transform any absolute URLs in your HTML to include this
|
||||||
// folder name and does **not** affect where things go in the output folder.
|
// folder name and does **not** affect where things go in the output folder.
|
||||||
pathPrefix: "/",
|
|
||||||
};
|
// pathPrefix: "/",
|
||||||
};
|
};
|
||||||
|
21
netlify.toml
21
netlify.toml
@ -1,24 +1,3 @@
|
|||||||
[build]
|
[build]
|
||||||
publish = "_site"
|
publish = "_site"
|
||||||
command = "npm run build"
|
command = "npm run build"
|
||||||
|
|
||||||
[[plugins]]
|
|
||||||
|
|
||||||
# Opt-in to the Netlify Lighthouse plugin (choose one):
|
|
||||||
|
|
||||||
# 1. Go to your site on https://app.netlify.com and navigate to the Integrations tab, search for the `Lighthouse` plugin
|
|
||||||
# 2. Or via `npm install -D @netlify/plugin-lighthouse`
|
|
||||||
|
|
||||||
# Read more: https://github.com/netlify/netlify-plugin-lighthouse
|
|
||||||
|
|
||||||
package = "@netlify/plugin-lighthouse"
|
|
||||||
|
|
||||||
# optional, fails build when a category is below a threshold
|
|
||||||
[plugins.inputs.thresholds]
|
|
||||||
performance = 1.0
|
|
||||||
accessibility = 1.0
|
|
||||||
best-practices = 1.0
|
|
||||||
seo = 1.0
|
|
||||||
|
|
||||||
[plugins.inputs]
|
|
||||||
output_path = "reports/lighthouse/index.html"
|
|
||||||
|
29
package.json
29
package.json
@ -1,14 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "eleventy-base-blog",
|
"name": "eleventy-base-blog",
|
||||||
"version": "8.0.0",
|
"version": "9.0.0",
|
||||||
"description": "A starter repository for a blog web site using the Eleventy site generator.",
|
"description": "A starter repository for a blog web site using the Eleventy site generator.",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npx @11ty/eleventy",
|
"build": "npx @11ty/eleventy",
|
||||||
|
"build-nocolor": "cross-env NODE_DISABLE_COLORS=1 npx @11ty/eleventy",
|
||||||
"build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/",
|
"build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/",
|
||||||
"start": "npx @11ty/eleventy --serve --quiet",
|
"start": "npx @11ty/eleventy --serve --quiet",
|
||||||
"debug": "DEBUG=Eleventy* npx @11ty/eleventy",
|
"start-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/ --serve --quiet",
|
||||||
"debugstart": "DEBUG=Eleventy* npx @11ty/eleventy --serve --quiet",
|
"debug": "cross-env DEBUG=Eleventy* npx @11ty/eleventy",
|
||||||
"benchmark": "DEBUG=Eleventy:Benchmark* npx @11ty/eleventy"
|
"debugstart": "cross-env DEBUG=Eleventy* npx @11ty/eleventy --serve --quiet",
|
||||||
|
"benchmark": "cross-env DEBUG=Eleventy:Benchmark* npx @11ty/eleventy"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -21,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -32,13 +35,17 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/11ty/eleventy-base-blog#readme",
|
"homepage": "https://github.com/11ty/eleventy-base-blog#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@11ty/eleventy": "^2.0.1",
|
"@11ty/eleventy": "^3.0.0",
|
||||||
"@11ty/eleventy-img": "^3.1.1",
|
"@11ty/eleventy-img": "^5.0.0",
|
||||||
"@11ty/eleventy-navigation": "^0.3.5",
|
"@11ty/eleventy-navigation": "^0.3.5",
|
||||||
"@11ty/eleventy-plugin-bundle": "^1.0.4",
|
"@11ty/eleventy-plugin-rss": "^2.0.2",
|
||||||
"@11ty/eleventy-plugin-rss": "^1.2.0",
|
|
||||||
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
|
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
|
||||||
"luxon": "^3.3.0",
|
"cross-env": "^7.0.3",
|
||||||
"markdown-it-anchor": "^8.6.7"
|
"luxon": "^3.5.0",
|
||||||
|
"zod": "^3.23.8",
|
||||||
|
"zod-validation-error": "^3.3.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@zachleat/heading-anchors": "^1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@view-transition {
|
||||||
|
navigation: auto;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -89,7 +93,8 @@ a[href]:active {
|
|||||||
color: var(--text-color-link-active);
|
color: var(--text-color-link-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main,
|
||||||
|
footer {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
main :first-child {
|
main :first-child {
|
||||||
@ -106,10 +111,19 @@ header:after {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.links-nextprev {
|
.links-nextprev {
|
||||||
list-style: none;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: .5em 1em;
|
||||||
|
list-style: "";
|
||||||
border-top: 1px dashed var(--color-gray-20);
|
border-top: 1px dashed var(--color-gray-20);
|
||||||
padding: 1em 0;
|
padding: 1em 0;
|
||||||
}
|
}
|
||||||
|
.links-nextprev > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.links-nextprev-next {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
@ -137,6 +151,7 @@ pre:not([class*="language-"]) {
|
|||||||
white-space: pre;
|
white-space: pre;
|
||||||
word-spacing: normal;
|
word-spacing: normal;
|
||||||
word-break: normal;
|
word-break: normal;
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
code {
|
code {
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
@ -245,26 +260,3 @@ header {
|
|||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Direct Links / Markdown Headers */
|
|
||||||
.header-anchor {
|
|
||||||
text-decoration: none;
|
|
||||||
font-style: normal;
|
|
||||||
font-size: 1em;
|
|
||||||
margin-left: .1em;
|
|
||||||
}
|
|
||||||
a[href].header-anchor,
|
|
||||||
a[href].header-anchor:visited {
|
|
||||||
color: transparent;
|
|
||||||
}
|
|
||||||
a[href].header-anchor:focus,
|
|
||||||
a[href].header-anchor:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
a[href].header-anchor:focus,
|
|
||||||
:hover > a[href].header-anchor {
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 + .header-anchor {
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
1
vercel.json
Normal file
1
vercel.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ "trailingSlash": true }
|
Loading…
Reference in New Issue
Block a user