initial commit
This commit is contained in:
commit
b2f00fd619
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
charset = utf-8
|
48
.github/workflows/gh-pages.yml.sample
vendored
Normal file
48
.github/workflows/gh-pages.yml.sample
vendored
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# If you’d like to deploy this to GitHub pages, rename this
|
||||||
|
# file to `gh-pages.yml` and read the mini-tutorial on
|
||||||
|
# https://www.11ty.dev/docs/deployment/#deploy-an-eleventy-project-to-github-pages
|
||||||
|
name: Deploy to GitHub Pages
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '18'
|
||||||
|
|
||||||
|
- name: Cache npm
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
|
||||||
|
|
||||||
|
- name: Cache Eleventy .cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ./.cache
|
||||||
|
key: ${{ runner.os }}-eleventy-fetch-cache
|
||||||
|
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run build-ghpages
|
||||||
|
|
||||||
|
- name: Deploy
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: ./_site
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
_site/
|
||||||
|
node_modules/
|
||||||
|
package-lock.json
|
||||||
|
.cache
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017–2023 Zach Leatherman @zachleat
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
121
README.md
Normal file
121
README.md
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
# eleventy-base-blog v8
|
||||||
|
|
||||||
|
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/)).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
* [Want a more generic/detailed getting started guide?](https://www.11ty.dev/docs/getting-started/)
|
||||||
|
|
||||||
|
1. Make a directory and navigate to it:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir my-blog-name
|
||||||
|
cd my-blog-name
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Clone this Repository
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/11ty/eleventy-base-blog.git .
|
||||||
|
```
|
||||||
|
|
||||||
|
_Optional:_ Review `eleventy.config.js` and `_data/metadata.js` to configure the site’s options and data.
|
||||||
|
|
||||||
|
3. Install dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run Eleventy
|
||||||
|
|
||||||
|
Generate a production-ready build to the `_site` folder:
|
||||||
|
|
||||||
|
```
|
||||||
|
npx @11ty/eleventy
|
||||||
|
```
|
||||||
|
|
||||||
|
Or build and host on a local development server:
|
||||||
|
|
||||||
|
```
|
||||||
|
npx @11ty/eleventy --serve
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can run [debug mode](https://www.11ty.dev/docs/debugging/) to see all the internals.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Using [Eleventy v2.0](https://www.11ty.dev/blog/eleventy-v2/) with zero-JavaScript output.
|
||||||
|
- 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/)
|
||||||
|
- 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/)
|
||||||
|
- **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_
|
||||||
|
- _0ms Total Blocking Time_
|
||||||
|
- 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/)
|
||||||
|
- [Image optimization](https://www.11ty.dev/docs/plugins/image/) via the `{% image %}` shortcode.
|
||||||
|
- Zero-JavaScript output.
|
||||||
|
- Support for modern image formats automatically (e.g. AVIF and WebP)
|
||||||
|
- 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`
|
||||||
|
- Includes `width`/`height` attributes to avoid [content layout shift](https://web.dev/cls/).
|
||||||
|
- Includes `loading="lazy"` for native lazy loading without JavaScript.
|
||||||
|
- Includes [`decoding="async"`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding)
|
||||||
|
- 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).
|
||||||
|
- Built-in [syntax highlighter](https://www.11ty.dev/docs/plugins/syntaxhighlight/) (zero-JavaScript output).
|
||||||
|
- 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
|
||||||
|
- Accessible deep links to headings
|
||||||
|
- Generated Pages
|
||||||
|
- Home, Archive, and About pages.
|
||||||
|
- [Feeds for Atom and JSON](https://www.11ty.dev/docs/plugins/rss/)
|
||||||
|
- `sitemap.xml`
|
||||||
|
- Zero-maintenance tag pages ([View on the Demo](https://eleventy-base-blog.netlify.app/tags/))
|
||||||
|
- Content not found (404) page
|
||||||
|
|
||||||
|
## Demos
|
||||||
|
|
||||||
|
- [Netlify](https://eleventy-base-blog.netlify.com/)
|
||||||
|
- [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
|
||||||
|
- [Remix on Glitch](https://glitch.com/~11ty-eleventy-base-blog)
|
||||||
|
- [Cloudflare Pages](https://eleventy-base-blog-d2a.pages.dev/)
|
||||||
|
|
||||||
|
## Deploy this to your own site
|
||||||
|
|
||||||
|
Deploy this Eleventy site in just a few clicks on these services:
|
||||||
|
|
||||||
|
- [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)
|
||||||
|
- 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)
|
||||||
|
- 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
|
||||||
|
|
||||||
|
- `content/about/index.md` is an example of a content page.
|
||||||
|
- `content/blog/` has the blog posts but really they can live in any directory. They need only the `posts` tag to be included in the blog posts [collection](https://www.11ty.dev/docs/collections/).
|
||||||
|
- 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`.
|
||||||
|
- 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/):
|
||||||
|
- `_includes/layouts/base.njk`: the top level HTML structure
|
||||||
|
- `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`)
|
||||||
|
- `_includes/layouts/post.njk`: the blog post template (wrapped into `base.njk`)
|
||||||
|
- `_includes/postslist.njk` is a Nunjucks include and is a reusable component used to display a list of all the posts. `content/index.njk` has an example of how to use it.
|
||||||
|
|
||||||
|
#### Content Security Policy
|
||||||
|
|
||||||
|
If your site enforces a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (as public-facing sites should), you have a few choices (pick one):
|
||||||
|
|
||||||
|
1. In `base.njk`, remove `<style>{% getBundle "css" %}</style>` and uncomment `<link rel="stylesheet" href="{% getBundleFileUrl "css" %}">`
|
||||||
|
2. Configure the server with the CSP directive `style-src: 'unsafe-inline'` (less secure).
|
11
_data/metadata.js
Normal file
11
_data/metadata.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module.exports = {
|
||||||
|
title: "Eleventy Base Blog v8",
|
||||||
|
url: "https://example.com/",
|
||||||
|
language: "en",
|
||||||
|
description: "I am writing about my experiences as a naval navel-gazer.",
|
||||||
|
author: {
|
||||||
|
name: "Your Name Here",
|
||||||
|
email: "youremailaddress@example.com",
|
||||||
|
url: "https://example.com/about-me/"
|
||||||
|
}
|
||||||
|
}
|
61
_includes/layouts/base.njk
Normal file
61
_includes/layouts/base.njk
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="{{ metadata.language }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ title or metadata.title }}</title>
|
||||||
|
<meta name="description" content="{{ description or metadata.description }}">
|
||||||
|
|
||||||
|
{#- 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! #}
|
||||||
|
{#- <meta name="generator" content="{{ eleventy.generator }}"> #}
|
||||||
|
|
||||||
|
{#-
|
||||||
|
CSS bundles are provided via the `eleventy-plugin-bundle` plugin:
|
||||||
|
1. You can add to them using `{% css %}`
|
||||||
|
2. You can get from them using `{% getBundle "css" %}` or `{% getBundleFileUrl "css" %}`
|
||||||
|
3. You can do the same for JS: {% js %}{% endjs %} and <script>{% getBundle "js" %}</script>
|
||||||
|
4. Learn more: https://github.com/11ty/eleventy-plugin-bundle
|
||||||
|
#}
|
||||||
|
|
||||||
|
{#- Add an arbitrary string to the bundle #}
|
||||||
|
{%- css %}* { box-sizing: border-box; }{% endcss %}
|
||||||
|
{#- Add the contents of a file to the bundle #}
|
||||||
|
{%- css %}{% include "public/css/index.css" %}{% endcss %}
|
||||||
|
{#- Or add from node_modules #}
|
||||||
|
{# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
|
||||||
|
|
||||||
|
{#- Render the CSS bundle using Inlined CSS (for the fastest site performance in production) #}
|
||||||
|
<style>{% getBundle "css" %}</style>
|
||||||
|
{#- 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" %}"> #}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="#skip" class="visually-hidden">Skip to main content</a>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<a href="/" class="home-link">{{ metadata.title }}</a>
|
||||||
|
|
||||||
|
{#- Read more about `eleventy-navigation` at https://www.11ty.dev/docs/plugins/navigation/ #}
|
||||||
|
<nav>
|
||||||
|
<h2 class="visually-hidden">Top level navigation menu</h2>
|
||||||
|
<ul class="nav">
|
||||||
|
{%- for entry in collections.all | eleventyNavigation %}
|
||||||
|
<li class="nav-item"><a href="{{ entry.url }}"{% if entry.url == page.url %} aria-current="page"{% endif %}>{{ entry.title }}</a></li>
|
||||||
|
{%- endfor %}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main id="skip">
|
||||||
|
{{ content | safe }}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer></footer>
|
||||||
|
|
||||||
|
<!-- This page `{{ page.url | htmlBaseUrl }}` was built on {% currentBuildDate %} -->
|
||||||
|
</body>
|
||||||
|
</html>
|
16
_includes/layouts/home.njk
Normal file
16
_includes/layouts/home.njk
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
layout: layouts/base.njk
|
||||||
|
---
|
||||||
|
<!-- Delete this message, it will also remove the component CSS from the bundle -->
|
||||||
|
{%- css %}{% include "public/css/message-box.css" %}{% endcss %}
|
||||||
|
<div class="message-box">
|
||||||
|
<ol>
|
||||||
|
<li>Edit the <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>Delete this message from <code>_includes/layouts/home.njk</code>.</li>
|
||||||
|
</ol>
|
||||||
|
<p><em>This is an <a href="https://www.11ty.dev/">Eleventy project</a> created from the <a href="https://github.com/11ty/eleventy-base-blog"><code>eleventy-base-blog</code> repo</a>.</em></p>
|
||||||
|
</div>
|
||||||
|
<!-- Stop deleting -->
|
||||||
|
|
||||||
|
{{ content | safe }}
|
28
_includes/layouts/post.njk
Normal file
28
_includes/layouts/post.njk
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
layout: layouts/base.njk
|
||||||
|
---
|
||||||
|
{# Only include the syntax highlighter CSS on blog posts #}
|
||||||
|
{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}
|
||||||
|
{%- css %}{% include "public/css/prism-diff.css" %}{%- endcss %}
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
|
||||||
|
<ul class="post-metadata">
|
||||||
|
<li><time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></li>
|
||||||
|
{%- for tag in tags | filterTagList %}
|
||||||
|
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
|
||||||
|
<li><a href="{{ tagUrl }}" class="post-tag">{{ tag }}</a>{%- if not loop.last %}, {% endif %}</li>
|
||||||
|
{%- endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{{ content | safe }}
|
||||||
|
|
||||||
|
{%- if collections.posts %}
|
||||||
|
{%- set previousPost = collections.posts | getPreviousCollectionItem %}
|
||||||
|
{%- set nextPost = collections.posts | getNextCollectionItem %}
|
||||||
|
{%- if nextPost or previousPost %}
|
||||||
|
<ul class="links-nextprev">
|
||||||
|
{%- if previousPost %}<li>Previous: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></li>{% endif %}
|
||||||
|
{%- if nextPost %}<li>Next: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></li>{% endif %}
|
||||||
|
</ul>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif %}
|
9
_includes/postslist.njk
Normal file
9
_includes/postslist.njk
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{%- css %}.postlist { counter-reset: start-from {{ (postslistCounter or postslist.length) + 1 }} }{% endcss %}
|
||||||
|
<ol reversed class="postlist">
|
||||||
|
{% for post in postslist | reverse %}
|
||||||
|
<li class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
|
||||||
|
<a href="{{ post.url }}" class="postlist-link">{% if post.data.title %}{{ post.data.title }}{% else %}<code>{{ post.url }}</code>{% endif %}</a>
|
||||||
|
<time class="postlist-date" datetime="{{ post.date | htmlDateString }}">{{ post.date | readableDate("LLLL yyyy") }}</time>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
19
content/404.md
Normal file
19
content/404.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
layout: layouts/home.njk
|
||||||
|
permalink: 404.html
|
||||||
|
eleventyExcludeFromCollections: true
|
||||||
|
---
|
||||||
|
# Content not found.
|
||||||
|
|
||||||
|
Go <a href="/">home</a>.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Read more: https://www.11ty.dev/docs/quicktips/not-found/
|
||||||
|
|
||||||
|
This will work for both GitHub pages and Netlify:
|
||||||
|
|
||||||
|
* https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/
|
||||||
|
* https://www.netlify.com/docs/redirects/#custom-404
|
||||||
|
|
||||||
|
-->
|
9
content/about/index.md
Normal file
9
content/about/index.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
layout: layouts/base.njk
|
||||||
|
eleventyNavigation:
|
||||||
|
key: About Me
|
||||||
|
order: 3
|
||||||
|
---
|
||||||
|
# About Me
|
||||||
|
|
||||||
|
I am a person that writes stuff.
|
10
content/blog.njk
Normal file
10
content/blog.njk
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
layout: layouts/home.njk
|
||||||
|
eleventyNavigation:
|
||||||
|
key: Archive
|
||||||
|
order: 2
|
||||||
|
---
|
||||||
|
<h1>Archive</h1>
|
||||||
|
|
||||||
|
{% set postslist = collections.posts %}
|
||||||
|
{% include "postslist.njk" %}
|
6
content/blog/blog.11tydata.js
Normal file
6
content/blog/blog.11tydata.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
tags: [
|
||||||
|
"posts"
|
||||||
|
],
|
||||||
|
"layout": "layouts/post.njk",
|
||||||
|
};
|
6
content/blog/fifthpost.md
Normal file
6
content/blog/fifthpost.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: This is a fifth post (draft)
|
||||||
|
date: 2023-01-23
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
This is a draft post
|
26
content/blog/firstpost.md
Normal file
26
content/blog/firstpost.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
title: This is my first post.
|
||||||
|
description: This is a post on My Blog about agile frameworks.
|
||||||
|
date: 2018-05-01
|
||||||
|
tags:
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Section Header
|
||||||
|
|
||||||
|
Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.
|
||||||
|
|
||||||
|
```diff-js
|
||||||
|
// this is a command
|
||||||
|
function myCommand() {
|
||||||
|
+ let counter = 0;
|
||||||
|
- let counter = 1;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a line break above this line.
|
||||||
|
console.log('Test');
|
||||||
|
```
|
16
content/blog/fourthpost/fourthpost.md
Normal file
16
content/blog/fourthpost/fourthpost.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
title: This is my fourth post!
|
||||||
|
description: This is a post on My Blog about touchpoints and circling wagons.
|
||||||
|
date: 2018-09-30
|
||||||
|
tags: second 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.
|
||||||
|
|
||||||
|
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" %}
|
||||||
|
|
||||||
|
## Section Header
|
||||||
|
|
||||||
|
Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.
|
||||||
|
|
BIN
content/blog/fourthpost/possum.png
Normal file
BIN
content/blog/fourthpost/possum.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 127 KiB |
17
content/blog/secondpost.md
Normal file
17
content/blog/secondpost.md
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
title: This is my second post with a much longer title.
|
||||||
|
description: This is a post on My Blog about leveraging agile frameworks.
|
||||||
|
date: 2018-07-04
|
||||||
|
tags:
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
## Section Header
|
||||||
|
|
||||||
|
<a href="/blog/firstpost/">First post</a>
|
||||||
|
<a href="/blog/thirdpost/">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.
|
||||||
|
|
||||||
|
Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.
|
45
content/blog/thirdpost.md
Normal file
45
content/blog/thirdpost.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
title: This is my third post.
|
||||||
|
description: This is a post on My Blog about win-win survival strategies.
|
||||||
|
date: 2018-08-24
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
### Styled (with Syntax)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// this is a command
|
||||||
|
function myCommand() {
|
||||||
|
let counter = 0;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a line break above this line.
|
||||||
|
console.log('Test');
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unstyled
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
```
|
||||||
|
// this is a command
|
||||||
|
function myCommand() {
|
||||||
|
let counter = 0;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test with a line break above this line.
|
||||||
|
console.log('Test');
|
||||||
|
```
|
||||||
|
|
||||||
|
## Section Header
|
||||||
|
|
||||||
|
Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.
|
3
content/feed/feed.11tydata.js
Normal file
3
content/feed/feed.11tydata.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
eleventyExcludeFromCollections: true
|
||||||
|
}
|
27
content/feed/feed.njk
Executable file
27
content/feed/feed.njk
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
# 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>
|
29
content/feed/json.njk
Normal file
29
content/feed/json.njk
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
---
|
||||||
|
# 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 %}
|
||||||
|
]
|
||||||
|
}
|
28
content/index.njk
Normal file
28
content/index.njk
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
layout: layouts/home.njk
|
||||||
|
eleventyNavigation:
|
||||||
|
key: Home
|
||||||
|
order: 1
|
||||||
|
numberOfLatestPostsToShow: 3
|
||||||
|
---
|
||||||
|
{% set postsCount = collections.posts | length %}
|
||||||
|
{% set latestPostsCount = postsCount | min(numberOfLatestPostsToShow) %}
|
||||||
|
<h1>Latest {{ latestPostsCount }} Post{% if latestPostsCount != 1 %}s{% endif %}</h1>
|
||||||
|
|
||||||
|
{% set postslist = collections.posts | head(-1 * numberOfLatestPostsToShow) %}
|
||||||
|
{% set postslistCounter = postsCount %}
|
||||||
|
{% include "postslist.njk" %}
|
||||||
|
|
||||||
|
{% set morePosts = postsCount - numberOfLatestPostsToShow %}
|
||||||
|
{% if morePosts > 0 %}
|
||||||
|
<p>{{ morePosts }} more post{% if morePosts != 1 %}s{% endif %} can be found in <a href="/blog/">the archive</a>.</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# List every content page in the project #}
|
||||||
|
{#
|
||||||
|
<ul>
|
||||||
|
{%- for entry in collections.all %}
|
||||||
|
<li><a href="{{ entry.url }}"><code>{{ entry.url }}</code></a></li>
|
||||||
|
{%- endfor %}
|
||||||
|
</ul>
|
||||||
|
#}
|
14
content/sitemap/sitemap.xml.njk
Normal file
14
content/sitemap/sitemap.xml.njk
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
permalink: /sitemap.xml
|
||||||
|
eleventyExcludeFromCollections: true
|
||||||
|
---
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||||
|
{%- for page in collections.all %}
|
||||||
|
{% set absoluteUrl %}{{ page.url | htmlBaseUrl(metadata.url) }}{% endset %}
|
||||||
|
<url>
|
||||||
|
<loc>{{ absoluteUrl }}</loc>
|
||||||
|
<lastmod>{{ page.date | htmlDateString }}</lastmod>
|
||||||
|
</url>
|
||||||
|
{%- endfor %}
|
||||||
|
</urlset>
|
12
content/tags-list.njk
Normal file
12
content/tags-list.njk
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
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>
|
22
content/tags.njk
Normal file
22
content/tags.njk
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
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 ] %}
|
||||||
|
{% include "postslist.njk" %}
|
||||||
|
|
||||||
|
<p>See <a href="/tags/">all tags</a>.</p>
|
50
eleventy.config.drafts.js
Normal file
50
eleventy.config.drafts.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
51
eleventy.config.images.js
Normal file
51
eleventy.config.images.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
};
|
144
eleventy.config.js
Normal file
144
eleventy.config.js
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
const { DateTime } = require("luxon");
|
||||||
|
const markdownItAnchor = require("markdown-it-anchor");
|
||||||
|
|
||||||
|
const pluginRss = require("@11ty/eleventy-plugin-rss");
|
||||||
|
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");
|
||||||
|
const pluginImages = require("./eleventy.config.images.js");
|
||||||
|
|
||||||
|
/** @param {import('@11ty/eleventy').UserConfig} eleventyConfig */
|
||||||
|
module.exports = function(eleventyConfig) {
|
||||||
|
// Copy the contents of the `public` folder to the output folder
|
||||||
|
// For example, `./public/css/` ends up in `_site/css/`
|
||||||
|
eleventyConfig.addPassthroughCopy({
|
||||||
|
"./public/": "/",
|
||||||
|
"./node_modules/prismjs/themes/prism-okaidia.css": "/css/prism-okaidia.css"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run Eleventy when these files change:
|
||||||
|
// https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets
|
||||||
|
|
||||||
|
// Watch content images for the image pipeline.
|
||||||
|
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
|
||||||
|
|
||||||
|
// App plugins
|
||||||
|
eleventyConfig.addPlugin(pluginDrafts);
|
||||||
|
eleventyConfig.addPlugin(pluginImages);
|
||||||
|
|
||||||
|
// Official plugins
|
||||||
|
eleventyConfig.addPlugin(pluginRss);
|
||||||
|
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
|
||||||
|
preAttributes: { tabindex: 0 }
|
||||||
|
});
|
||||||
|
eleventyConfig.addPlugin(pluginNavigation);
|
||||||
|
eleventyConfig.addPlugin(EleventyHtmlBasePlugin);
|
||||||
|
eleventyConfig.addPlugin(pluginBundle);
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
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 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", () => {
|
||||||
|
return (new Date()).toISOString();
|
||||||
|
})
|
||||||
|
|
||||||
|
// Features to make your build faster (when you need them)
|
||||||
|
|
||||||
|
// If your passthrough copy gets heavy and cumbersome, add this line
|
||||||
|
// to emulate the file copy on the dev server. Learn more:
|
||||||
|
// https://www.11ty.dev/docs/copy/#emulate-passthrough-copy-during-serve
|
||||||
|
|
||||||
|
// eleventyConfig.setServerPassthroughCopyBehavior("passthrough");
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Control which files Eleventy will process
|
||||||
|
// e.g.: *.md, *.njk, *.html, *.liquid
|
||||||
|
templateFormats: [
|
||||||
|
"md",
|
||||||
|
"njk",
|
||||||
|
"html",
|
||||||
|
"liquid",
|
||||||
|
],
|
||||||
|
|
||||||
|
// Pre-process *.md files with: (default: `liquid`)
|
||||||
|
markdownTemplateEngine: "njk",
|
||||||
|
|
||||||
|
// Pre-process *.html files with: (default: `liquid`)
|
||||||
|
htmlTemplateEngine: "njk",
|
||||||
|
|
||||||
|
// These are all optional:
|
||||||
|
dir: {
|
||||||
|
input: "content", // default: "."
|
||||||
|
includes: "../_includes", // default: "_includes"
|
||||||
|
data: "../_data", // default: "_data"
|
||||||
|
output: "_site"
|
||||||
|
},
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Optional items:
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
// If your site deploys to a subdirectory, change `pathPrefix`.
|
||||||
|
// Read more: https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// folder name and does **not** affect where things go in the output folder.
|
||||||
|
pathPrefix: "/",
|
||||||
|
};
|
||||||
|
};
|
24
netlify.toml
Normal file
24
netlify.toml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[build]
|
||||||
|
publish = "_site"
|
||||||
|
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"
|
44
package.json
Normal file
44
package.json
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"name": "eleventy-base-blog",
|
||||||
|
"version": "8.0.0",
|
||||||
|
"description": "A starter repository for a blog web site using the Eleventy site generator.",
|
||||||
|
"scripts": {
|
||||||
|
"build": "npx @11ty/eleventy",
|
||||||
|
"build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/",
|
||||||
|
"start": "npx @11ty/eleventy --serve --quiet",
|
||||||
|
"debug": "DEBUG=Eleventy* npx @11ty/eleventy",
|
||||||
|
"debugstart": "DEBUG=Eleventy* npx @11ty/eleventy --serve --quiet",
|
||||||
|
"benchmark": "DEBUG=Eleventy:Benchmark* npx @11ty/eleventy"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/11ty/eleventy-base-blog.git"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "Zach Leatherman",
|
||||||
|
"email": "zachleatherman@gmail.com",
|
||||||
|
"url": "https://zachleat.com/"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/11ty"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/11ty/eleventy-base-blog/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/11ty/eleventy-base-blog#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"@11ty/eleventy": "^2.0.1",
|
||||||
|
"@11ty/eleventy-img": "^3.1.1",
|
||||||
|
"@11ty/eleventy-navigation": "^0.3.5",
|
||||||
|
"@11ty/eleventy-plugin-bundle": "^1.0.4",
|
||||||
|
"@11ty/eleventy-plugin-rss": "^1.2.0",
|
||||||
|
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
|
||||||
|
"luxon": "^3.3.0",
|
||||||
|
"markdown-it-anchor": "^8.6.7"
|
||||||
|
}
|
||||||
|
}
|
270
public/css/index.css
Normal file
270
public/css/index.css
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
/* Defaults */
|
||||||
|
:root {
|
||||||
|
--font-family: -apple-system, system-ui, sans-serif;
|
||||||
|
--font-family-monospace: Consolas, Menlo, Monaco, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Courier New, Courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Theme colors */
|
||||||
|
:root {
|
||||||
|
--color-gray-20: #e0e0e0;
|
||||||
|
--color-gray-50: #C0C0C0;
|
||||||
|
--color-gray-90: #333;
|
||||||
|
|
||||||
|
--background-color: #fff;
|
||||||
|
|
||||||
|
--text-color: var(--color-gray-90);
|
||||||
|
--text-color-link: #082840;
|
||||||
|
--text-color-link-active: #5f2b48;
|
||||||
|
--text-color-link-visited: #17050F;
|
||||||
|
|
||||||
|
--syntax-tab-size: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--color-gray-20: #e0e0e0;
|
||||||
|
--color-gray-50: #C0C0C0;
|
||||||
|
--color-gray-90: #dad8d8;
|
||||||
|
|
||||||
|
/* --text-color is assigned to --color-gray-_ above */
|
||||||
|
--text-color-link: #1493fb;
|
||||||
|
--text-color-link-active: #6969f7;
|
||||||
|
--text-color-link-visited: #a6a6f8;
|
||||||
|
|
||||||
|
--background-color: #15202b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Global stylesheet */
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
font-family: var(--font-family);
|
||||||
|
color: var(--text-color);
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
max-width: 40em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://www.a11yproject.com/posts/how-to-hide-content/ */
|
||||||
|
.visually-hidden {
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
clip-path: inset(50%);
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href] {
|
||||||
|
color: var(--text-color-link);
|
||||||
|
}
|
||||||
|
a[href]:visited {
|
||||||
|
color: var(--text-color-link-visited);
|
||||||
|
}
|
||||||
|
a[href]:hover,
|
||||||
|
a[href]:active {
|
||||||
|
color: var(--text-color-link-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
main :first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
border-bottom: 1px dashed var(--color-gray-20);
|
||||||
|
}
|
||||||
|
header:after {
|
||||||
|
content: "";
|
||||||
|
display: table;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.links-nextprev {
|
||||||
|
list-style: none;
|
||||||
|
border-top: 1px dashed var(--color-gray-20);
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
table td,
|
||||||
|
table th {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code {
|
||||||
|
font-family: var(--font-family-monospace);
|
||||||
|
}
|
||||||
|
pre:not([class*="language-"]) {
|
||||||
|
margin: .5em 0;
|
||||||
|
line-height: 1.375; /* 22px /16 */
|
||||||
|
-moz-tab-size: var(--syntax-tab-size);
|
||||||
|
-o-tab-size: var(--syntax-tab-size);
|
||||||
|
tab-size: var(--syntax-tab-size);
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
gap: 1em .5em;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
.home-link {
|
||||||
|
font-size: 1em; /* 16px /16 */
|
||||||
|
font-weight: 700;
|
||||||
|
margin-right: 2em;
|
||||||
|
}
|
||||||
|
.home-link:link:not(:hover) {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav */
|
||||||
|
.nav {
|
||||||
|
display: flex;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.nav-item {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
.nav-item a[href]:not(:hover) {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.nav a[href][aria-current="page"] {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Posts list */
|
||||||
|
.postlist {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
.postlist-item {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: baseline;
|
||||||
|
counter-increment: start-from -1;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.postlist-item:before {
|
||||||
|
display: inline-block;
|
||||||
|
pointer-events: none;
|
||||||
|
content: "" counter(start-from, decimal-leading-zero) ". ";
|
||||||
|
line-height: 100%;
|
||||||
|
text-align: right;
|
||||||
|
margin-left: -1.5rem;
|
||||||
|
}
|
||||||
|
.postlist-date,
|
||||||
|
.postlist-item:before {
|
||||||
|
font-size: 0.8125em; /* 13px /16 */
|
||||||
|
color: var(--color-gray-90);
|
||||||
|
}
|
||||||
|
.postlist-date {
|
||||||
|
word-spacing: -0.5px;
|
||||||
|
}
|
||||||
|
.postlist-link {
|
||||||
|
font-size: 1.1875em; /* 19px /16 */
|
||||||
|
font-weight: 700;
|
||||||
|
flex-basis: calc(100% - 1.5rem);
|
||||||
|
padding-left: .25em;
|
||||||
|
padding-right: .5em;
|
||||||
|
text-underline-position: from-font;
|
||||||
|
text-underline-offset: 0;
|
||||||
|
text-decoration-thickness: 1px;
|
||||||
|
}
|
||||||
|
.postlist-item-active .postlist-link {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tags */
|
||||||
|
.post-tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-transform: capitalize;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.postlist-item > .post-tag {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tags list */
|
||||||
|
.post-metadata {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: .5em;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.post-metadata time {
|
||||||
|
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;
|
||||||
|
}
|
18
public/css/message-box.css
Normal file
18
public/css/message-box.css
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* Message Box */
|
||||||
|
.message-box {
|
||||||
|
--color-message-box: #ffc;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
background-color: var(--color-message-box);
|
||||||
|
color: var(--color-gray-90);
|
||||||
|
padding: 1em 0.625em; /* 16px 10px /16 */
|
||||||
|
}
|
||||||
|
.message-box ol {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.message-box {
|
||||||
|
--color-message-box: #082840;
|
||||||
|
}
|
||||||
|
}
|
45
public/css/prism-diff.css
Normal file
45
public/css/prism-diff.css
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* New diff- syntax
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre[class*="language-diff-"] {
|
||||||
|
--eleventy-code-padding: 1.25em;
|
||||||
|
padding-left: var(--eleventy-code-padding);
|
||||||
|
padding-right: var(--eleventy-code-padding);
|
||||||
|
}
|
||||||
|
.token.deleted {
|
||||||
|
background-color: hsl(0, 51%, 37%);
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
.token.inserted {
|
||||||
|
background-color: hsl(126, 31%, 39%);
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the + and - characters unselectable for copy/paste */
|
||||||
|
.token.prefix.unchanged,
|
||||||
|
.token.prefix.inserted,
|
||||||
|
.token.prefix.deleted {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
.token.prefix.inserted,
|
||||||
|
.token.prefix.deleted {
|
||||||
|
width: var(--eleventy-code-padding);
|
||||||
|
background-color: rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Optional: full-width background color */
|
||||||
|
.token.inserted:not(.prefix),
|
||||||
|
.token.deleted:not(.prefix) {
|
||||||
|
display: block;
|
||||||
|
margin-left: calc(-1 * var(--eleventy-code-padding));
|
||||||
|
margin-right: calc(-1 * var(--eleventy-code-padding));
|
||||||
|
text-decoration: none; /* override del, ins, mark defaults */
|
||||||
|
color: inherit; /* override del, ins, mark defaults */
|
||||||
|
}
|
0
public/img/.gitkeep
Normal file
0
public/img/.gitkeep
Normal file
Loading…
Reference in a new issue