rework layout and add table of contents
This commit is contained in:
parent
33d6838dc4
commit
5817d94043
41
package-lock.json
generated
41
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@sveltejs/adapter-static": "^1.0.0-next.21",
|
"@sveltejs/adapter-static": "^1.0.0-next.21",
|
||||||
"@sveltejs/kit": "next",
|
"@sveltejs/kit": "next",
|
||||||
"hast-util-to-text": "^3.1.2",
|
"hast-util-to-text": "^3.1.2",
|
||||||
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"mdsvex": "^0.9.8",
|
"mdsvex": "^0.9.8",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^6.0.1",
|
||||||
"svelte": "^3.42.6",
|
"svelte": "^3.42.6",
|
||||||
@ -171,6 +172,15 @@
|
|||||||
"@types/unist": "^2"
|
"@types/unist": "^2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/mdast": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-YLeG8CujC9adtj/kuDzq1N4tCDYKoZ5l/bnjq8d74+t/3q/tHquJOJKUQXJrLCflOHpKjXgcI/a929gpmLOEng==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/unist": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/minimist": {
|
"node_modules/@types/minimist": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
|
||||||
@ -1773,6 +1783,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-to-string": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdsvex": {
|
"node_modules/mdsvex": {
|
||||||
"version": "0.9.8",
|
"version": "0.9.8",
|
||||||
"resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.9.8.tgz",
|
"resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.9.8.tgz",
|
||||||
@ -3613,6 +3636,15 @@
|
|||||||
"@types/unist": "^2"
|
"@types/unist": "^2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/mdast": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-YLeG8CujC9adtj/kuDzq1N4tCDYKoZ5l/bnjq8d74+t/3q/tHquJOJKUQXJrLCflOHpKjXgcI/a929gpmLOEng==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/unist": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/minimist": {
|
"@types/minimist": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
|
||||||
@ -4778,6 +4810,15 @@
|
|||||||
"integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
|
"integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"mdast-util-to-string": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/mdast": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mdsvex": {
|
"mdsvex": {
|
||||||
"version": "0.9.8",
|
"version": "0.9.8",
|
||||||
"resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.9.8.tgz",
|
"resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.9.8.tgz",
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
"svelte-preprocess": "^4.9.8",
|
"svelte-preprocess": "^4.9.8",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
"unist-util-find": "^2.0.0",
|
"unist-util-find": "^2.0.0",
|
||||||
"hast-util-to-text": "^3.1.2"
|
"hast-util-to-text": "^3.1.2",
|
||||||
|
"mdast-util-to-string": "^4.0.0"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,31 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.page {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(0, var(--content-width)) minmax(0, 1fr);
|
||||||
|
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
grid-column: 2 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-gutter {
|
||||||
|
grid-column: 1 / 2;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-top: -0.5rem;
|
margin-top: -0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post {
|
||||||
|
grid-column: 2 / 3;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -28,9 +48,17 @@
|
|||||||
<link rel="stylesheet" href="/prism-dracula.css" />
|
<link rel="stylesheet" href="/prism-dracula.css" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div id="post">
|
<div class="page">
|
||||||
<h1 id="{makeSlug(title)}">{title}</h1>
|
<div class="title">
|
||||||
<p class="subtitle">{formatDate(date)}</p>
|
<h1 id="{makeSlug(title)}">{title}</h1>
|
||||||
<Toc items={toc} />
|
<p class="subtitle">{formatDate(date)}</p>
|
||||||
<slot></slot>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="left-gutter">
|
||||||
|
<Toc items={toc} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="post">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -115,18 +115,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// /* slight tweaks for in between state */
|
|
||||||
// @media (min-width: 52.5em) and (max-width: 70em) {
|
|
||||||
// .sidenote {
|
|
||||||
// padding-left: calc(50vw - 19rem);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// @media (max-width: 52.5em) {
|
|
||||||
// .sidenote {
|
|
||||||
// padding-left: 2rem;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script context="module">
|
<script context="module">
|
||||||
|
@ -1,32 +1,66 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
import { makeSlug } from '$lib/utils.js';
|
import { makeSlug } from '$lib/utils.js';
|
||||||
|
|
||||||
export let items;
|
export let items;
|
||||||
|
|
||||||
console.log(items);
|
items.forEach(i => i.slug = makeSlug(i.text));
|
||||||
|
|
||||||
|
const selector = 'h1[id], h2[id], h3[id], h4[id], h6[id]';
|
||||||
|
let currentHeadingSlug = null;
|
||||||
|
function setCurrentHeading() {
|
||||||
|
for (const h of document.querySelectorAll(selector)) {
|
||||||
|
const yPos = h.getBoundingClientRect().y;
|
||||||
|
if (yPos > (window.innerHeight / 3)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentHeadingSlug = h.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount (() => {
|
||||||
|
document.addEventListener('scroll', setCurrentHeading);
|
||||||
|
setCurrentHeading();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* move everything out to the left and center it vertically */
|
/* move everything out to the left and center it vertically */
|
||||||
#toc {
|
#toc {
|
||||||
position: fixed;
|
position: sticky;
|
||||||
left: 1rem;
|
top: 1.5rem;
|
||||||
/* setting top at 50vh sticks it halfway down the viewport,
|
margin-right: 4rem;
|
||||||
then translating back up by 50% gets it vertically centered
|
|
||||||
even with a dynamic width */
|
max-width: 14rem;
|
||||||
top: 50vh;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
color: var(--content-color-faded);
|
color: var(--content-color-faded);
|
||||||
|
opacity: 0;
|
||||||
|
animation: fade-in 600ms ease-out;
|
||||||
|
animation-delay: 500ms;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* margin-left is to match the list items; this allows the accent bar
|
@keyframes fade-in {
|
||||||
for the current item to appear to float out in space */
|
from {opacity: 0}
|
||||||
|
to {opacity: 100%}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* margin-left is to match the padding on the top-level list items,
|
||||||
|
but here it needs to be margin so that the border is also shifted */
|
||||||
h5 {
|
h5 {
|
||||||
margin-left: 0.5rem;
|
|
||||||
padding-bottom: 0.25em;
|
|
||||||
margin-bottom: 0.25em;
|
|
||||||
border-bottom: 0.1em solid currentcolor;
|
|
||||||
font-variant: petite-caps;
|
font-variant: petite-caps;
|
||||||
|
font-weight: 500;
|
||||||
|
max-width: fit-content;
|
||||||
|
|
||||||
|
margin-top: 0;
|
||||||
|
/* 0.5rem for indent, 0.1rem for border */
|
||||||
|
margin-left: 0.6rem;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
padding-bottom: 0.25em;
|
||||||
|
|
||||||
|
border-bottom: 1px solid currentcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
@ -35,13 +69,21 @@
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* margin for indentation, padding so that the accent bar for the current
|
||||||
|
item isn't right on top of it */
|
||||||
li {
|
li {
|
||||||
margin-left: var(--indent, 0);
|
margin-left: var(--indent, 0);
|
||||||
padding-left: 0.5rem;
|
padding-left: 0.5rem;
|
||||||
margin-bottom: 0.15rem;
|
margin-bottom: 0.15rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
border-left: 0.1rem solid transparent;
|
||||||
|
}
|
||||||
|
li:hover {
|
||||||
|
color: var(--content-color);
|
||||||
|
border-left: 0.1rem solid var(--accent-color);
|
||||||
}
|
}
|
||||||
li.current {
|
li.current {
|
||||||
|
color: var(--content-color);
|
||||||
border-left: 0.1rem solid var(--accent-color);
|
border-left: 0.1rem solid var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,18 +91,20 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<div id="toc">
|
<div id="toc">
|
||||||
<h5>Table of Contents</h5>
|
<h5>
|
||||||
|
<span class="heading">Contents</span>
|
||||||
|
</h5>
|
||||||
<ul>
|
<ul>
|
||||||
{#each items as item}
|
{#each items as item}
|
||||||
<li style:--indent="{(item.depth - 2) * 0.75}em">
|
<li
|
||||||
<a href="#{makeSlug(item.text)}">{item.text}</a>
|
style:--indent="{(item.depth - 2) * 0.75}em"
|
||||||
|
class:current={item.slug === currentHeadingSlug}
|
||||||
|
>
|
||||||
|
<a href="#{item.slug}">{item.text}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1,39 +1,43 @@
|
|||||||
<style>
|
<script>
|
||||||
:global(main) {
|
import Toc from '$lib/Toc.svelte';
|
||||||
--content-width: 42rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
max-width: var(--content-width);
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header {
|
const items = [
|
||||||
|
{depth: 2, text: 'The Suboptimal Solution: Absolute Positioning'},
|
||||||
|
{depth: 2, text: 'CSS Wizardry'},
|
||||||
|
{depth: 2, text: 'Implementation'},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.header {
|
||||||
|
grid-column-start: 1;
|
||||||
|
grid-column-end: 4;
|
||||||
background-color: #4f5f68;
|
background-color: #4f5f68;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav-main {
|
nav {
|
||||||
max-width: 30rem;
|
max-width: 30rem;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(3, minmax(6rem, 8rem));
|
justify-content: space-around;
|
||||||
justify-content: space-between;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav-main a {
|
nav a {
|
||||||
|
width: 8rem;
|
||||||
|
min-width: 6rem;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0.25rem 0;
|
padding: 0.25rem 0;
|
||||||
}
|
}
|
||||||
|
nav a:hover {
|
||||||
#nav-main a:hover {
|
|
||||||
background-color: #00000025;
|
background-color: #00000025;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div id="header">
|
<div class="header">
|
||||||
<nav id="nav-main">
|
<nav>
|
||||||
<a sveltekit:prefetch href="/">Home</a>
|
<a sveltekit:prefetch href="/">Home</a>
|
||||||
<a sveltekit:prefetch href="/posts">Posts</a>
|
<a sveltekit:prefetch href="/posts">Posts</a>
|
||||||
<a sveltekit:prefetch href="/">About</a>
|
<a sveltekit:prefetch href="/">About</a>
|
||||||
|
@ -29,10 +29,12 @@ html {
|
|||||||
line-height: var(--content-line-height);
|
line-height: var(--content-line-height);
|
||||||
letter-spacing: -0.005em;
|
letter-spacing: -0.005em;
|
||||||
color: var(--content-color);
|
color: var(--content-color);
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
--content-width: 42rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { mdsvex } from 'mdsvex';
|
import { mdsvex } from 'mdsvex';
|
||||||
import staticAdapter from '@sveltejs/adapter-static';
|
import staticAdapter from '@sveltejs/adapter-static';
|
||||||
import svp from 'svelte-preprocess';
|
import svp from 'svelte-preprocess';
|
||||||
// import slug from './src/lib/slug.js';
|
|
||||||
// import { addDropcaps } from './src/lib/dropcapify.js';
|
import { localRemark } from './src/plugins/remark.js';
|
||||||
import { localPlugins } from './src/plugins/rehype.js';
|
import { localRehype } from './src/plugins/rehype.js';
|
||||||
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
@ -11,7 +11,8 @@ const config = {
|
|||||||
preprocess: [
|
preprocess: [
|
||||||
mdsvex({
|
mdsvex({
|
||||||
layout: './src/lib/Post.svelte',
|
layout: './src/lib/Post.svelte',
|
||||||
rehypePlugins: [localPlugins],
|
remarkPlugins: [localRemark],
|
||||||
|
rehypePlugins: [localRehype],
|
||||||
}),
|
}),
|
||||||
svp.scss(),
|
svp.scss(),
|
||||||
],
|
],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user