add heading slugs
This commit is contained in:
parent
cb04687d0b
commit
14d74ccdee
@ -1,5 +1,6 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
import { formatDate } from './datefmt.js';
|
import { formatDate } from './datefmt.js';
|
||||||
|
import { makeSlug } from '$lib/slug.js';
|
||||||
import Link from './Link.svelte';
|
import Link from './Link.svelte';
|
||||||
export { Link as a };
|
export { Link as a };
|
||||||
</script>
|
</script>
|
||||||
@ -13,7 +14,7 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div id="post">
|
<div id="post">
|
||||||
<h1>{title}</h1>
|
<h1 id="{makeSlug(title)}">{title}</h1>
|
||||||
<p><em>{formatDate(date)}</em></p>
|
<p><em>{formatDate(date)}</em></p>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,50 @@
|
|||||||
// this approach won't work if an attribute value contains ">"
|
const nonAlphaNum = /[^A-Za-z0-9\-]/g;
|
||||||
const tag = /<[^>]*?>/g
|
|
||||||
const nonAlphaNum = /[^A-Za-z0-9\-]/g
|
|
||||||
const space = /\s/g
|
const space = /\s/g
|
||||||
|
|
||||||
export default function slugify(text) {
|
export function makeSlug(text) {
|
||||||
return text.replace(tag, '')
|
return text
|
||||||
|
.toLowerCase()
|
||||||
.replace(space, '-')
|
.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);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import { mdsvex } from 'mdsvex';
|
import { mdsvex } from 'mdsvex';
|
||||||
import staticAdapter from '@sveltejs/adapter-static';
|
import staticAdapter from '@sveltejs/adapter-static';
|
||||||
|
import slug from './src/lib/slug.js';
|
||||||
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
extensions: ['.svelte', '.svx'],
|
extensions: ['.svelte', '.svx'],
|
||||||
preprocess: mdsvex({layout: './src/lib/Post.svelte'}),
|
preprocess: mdsvex({
|
||||||
|
layout: './src/lib/Post.svelte',
|
||||||
|
rehypePlugins: [slug],
|
||||||
|
}),
|
||||||
kit: {
|
kit: {
|
||||||
// hydrate the <div id="svelte"> element in src/app.html
|
// hydrate the <div id="svelte"> element in src/app.html
|
||||||
target: '#svelte',
|
target: '#svelte',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user