Swap to use IdAttributePlugin instead of markdown-it-anchor

This commit is contained in:
Zach Leatherman 2024-07-16 15:45:08 -05:00
parent 49610beab3
commit 1c3c777a1e
5 changed files with 74 additions and 28 deletions

View File

@ -32,6 +32,8 @@
<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" %}"> #}
{%- js %}{% include "public/js/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,7 +53,9 @@
</header> </header>
<main id="skip"> <main id="skip">
{{ content | safe }} <heading-anchors>
{{ content | safe }}
</heading-anchors>
</main> </main>
<footer> <footer>
@ -59,5 +63,6 @@
</footer> </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>

View File

@ -1,6 +1,4 @@
import markdownItAnchor from "markdown-it-anchor"; import { IdAttributePlugin, InputPathToUrlTransformPlugin, HtmlBasePlugin } from "@11ty/eleventy";
import { InputPathToUrlTransformPlugin, HtmlBasePlugin } from "@11ty/eleventy";
import { feedPlugin } from "@11ty/eleventy-plugin-rss"; import { feedPlugin } from "@11ty/eleventy-plugin-rss";
import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight"; import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import pluginNavigation from "@11ty/eleventy-navigation"; import pluginNavigation from "@11ty/eleventy-navigation";
@ -28,8 +26,8 @@ export default async function(eleventyConfig) {
// Per-page bundles, see https://github.com/11ty/eleventy-plugin-bundle // Per-page bundles, see https://github.com/11ty/eleventy-plugin-bundle
// Adds the {% css %} paired shortcode // Adds the {% css %} paired shortcode
eleventyConfig.addBundle("css"); eleventyConfig.addBundle("css");
// Do you want a {% js %} bundle shortcode too? // Adds the {% js %} paired shortcode
// eleventyConfig.addBundle("js"); eleventyConfig.addBundle("js");
// Official plugins // Official plugins
eleventyConfig.addPlugin(pluginSyntaxHighlight, { eleventyConfig.addPlugin(pluginSyntaxHighlight, {
@ -84,20 +82,27 @@ export default async function(eleventyConfig) {
// Filters // Filters
eleventyConfig.addPlugin(pluginFilters); eleventyConfig.addPlugin(pluginFilters);
// Customize Markdown library settings: eleventyConfig.addPlugin(IdAttributePlugin, {
eleventyConfig.amendLibrary("md", mdLib => { // by default we use Eleventys built-in `slugify` filter:
mdLib.use(markdownItAnchor, { // slugify: eleventyConfig.getFilter("slugify"),
permalink: markdownItAnchor.permalink.ariaHidden({ // default:
placement: "after", // selector: "h1,h2,h3,h4,h5,h6",
class: "header-anchor",
symbol: "#",
ariaHidden: false,
}),
level: [1,2,3,4],
slugify: eleventyConfig.getFilter("slugify")
});
}); });
// 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();
}); });

View File

@ -35,14 +35,13 @@
}, },
"homepage": "https://github.com/11ty/eleventy-base-blog#readme", "homepage": "https://github.com/11ty/eleventy-base-blog#readme",
"devDependencies": { "devDependencies": {
"@11ty/eleventy": "3.0.0-alpha.16", "@11ty/eleventy": "3.0.0-alpha.17",
"@11ty/eleventy-img": "5.0.0-beta.5", "@11ty/eleventy-img": "5.0.0-beta.5",
"@11ty/eleventy-navigation": "^0.3.5", "@11ty/eleventy-navigation": "^0.3.5",
"@11ty/eleventy-plugin-rss": "2.0.0-beta.8", "@11ty/eleventy-plugin-rss": "2.0.0-beta.8",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"luxon": "^3.4.4", "luxon": "^3.4.4",
"markdown-it-anchor": "^8.6.7",
"zod": "^3.23.8", "zod": "^3.23.8",
"zod-validation-error": "^3.3.0" "zod-validation-error": "^3.3.0"
} }

View File

@ -257,25 +257,25 @@ header {
} }
/* Direct Links / Markdown Headers */ /* Direct Links / Markdown Headers */
.header-anchor { .heading-anchor {
text-decoration: none; text-decoration: none;
font-style: normal; font-style: normal;
font-size: 1em; font-size: 1em;
margin-left: .1em; margin-left: .1em;
} }
a[href].header-anchor, a[href].heading-anchor,
a[href].header-anchor:visited { a[href].heading-anchor:visited {
color: transparent; color: transparent;
} }
a[href].header-anchor:focus, a[href].heading-anchor:focus,
a[href].header-anchor:hover { a[href].heading-anchor:hover {
text-decoration: underline; text-decoration: underline;
} }
a[href].header-anchor:focus, a[href].heading-anchor:focus,
:hover > a[href].header-anchor { :hover > a[href].heading-anchor {
color: #aaa; color: #aaa;
} }
h2 + .header-anchor { h2 + .heading-anchor {
font-size: 1.5em; font-size: 1.5em;
} }

View File

@ -0,0 +1,37 @@
// Thank you to https://github.com/daviddarnes/heading-anchors
class HeadingAnchors extends HTMLElement {
static register(tagName) {
if ("customElements" in window) {
customElements.define(tagName || "heading-anchors", HeadingAnchors);
}
}
connectedCallback() {
this.headings.forEach((heading) => {
if(!heading.querySelector("a.direct-link") || heading.hasAttribute("data-heading-anchors-optout")) {
heading.append(this.anchor(heading));
}
});
}
anchor(heading) {
// TODO this would be good use case for shadow dom
let anchor = document.createElement("a");
anchor.setAttribute("data-pagefind-ignore", "");
anchor.href = `#${heading.id}`;
anchor.classList.add("heading-anchor");
anchor.innerHTML = `<span class="visually-hidden">Jump to heading</span><span aria-hidden="true">#</span>`;
return anchor;
}
get headings() {
return this.querySelectorAll(this.selector.split(",").map(entry => `${entry.trim()}[id]`));
}
get selector() {
return this.getAttribute("selector") || "h1,h2,h3,h4"
}
}
HeadingAnchors.register();