add heading slugs

This commit is contained in:
Joseph Montanaro 2021-10-21 21:25:28 -07:00
parent cb04687d0b
commit 14d74ccdee
3 changed files with 54 additions and 9 deletions

View File

@ -1,5 +1,6 @@
<script context="module">
import { formatDate } from './datefmt.js';
import { makeSlug } from '$lib/slug.js';
import Link from './Link.svelte';
export { Link as a };
</script>
@ -13,7 +14,7 @@
</svelte:head>
<div id="post">
<h1>{title}</h1>
<h1 id="{makeSlug(title)}">{title}</h1>
<p><em>{formatDate(date)}</em></p>
<slot></slot>
</div>

View File

@ -1,10 +1,50 @@
// this approach won't work if an attribute value contains ">"
const tag = /<[^>]*?>/g
const nonAlphaNum = /[^A-Za-z0-9\-]/g
const nonAlphaNum = /[^A-Za-z0-9\-]/g;
const space = /\s/g
export default function slugify(text) {
return text.replace(tag, '')
export function makeSlug(text) {
return text
.toLowerCase()
.replace(space, '-')
.replace(nonAlphNum, '')
}
.replace(nonAlphaNum, '')
}
function apply(node, types, fn) {
if (typeof types === 'string') {
types = new Set([types]);
}
else if (!(types instanceof Set)) {
types = new Set(types)
console.log(types)
}
if (types.has(node.type)) {
fn(node);
}
if ('children' in node) {
for (let child of node.children) {
apply(child, types, fn);
}
}
}
function getTextContent(node) {
let segments = [];
apply(node, 'text', textNode => {
// skip all-whitespace strings
if (textNode.value.match(/^\s+$/)) return;
segments.push(textNode.value.trim());
});
return segments.join(' ');
}
export default function slug() {
return (tree) => {
apply(tree, 'element', e => {
if (e.tagName.match(/h[1-6]/)) {
let text = getTextContent(e);
e.properties.id = makeSlug(text);
}
})
}
}

View File

@ -1,10 +1,14 @@
import { mdsvex } from 'mdsvex';
import staticAdapter from '@sveltejs/adapter-static';
import slug from './src/lib/slug.js';
const config = {
extensions: ['.svelte', '.svx'],
preprocess: mdsvex({layout: './src/lib/Post.svelte'}),
preprocess: mdsvex({
layout: './src/lib/Post.svelte',
rehypePlugins: [slug],
}),
kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',